dobo 1.0.13 → 1.0.14

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.
Files changed (42) hide show
  1. package/bajo/init.js +2 -2
  2. package/bajo/method/attachment/copy-uploaded.js +2 -2
  3. package/bajo/method/attachment/create.js +2 -2
  4. package/bajo/method/attachment/remove.js +1 -1
  5. package/bajo/method/get-schema.js +1 -1
  6. package/bajo/method/model/exists.js +1 -1
  7. package/bajo/method/prep-pagination.js +1 -1
  8. package/bajo/method/record/create.js +1 -1
  9. package/bajo/method/record/remove.js +1 -1
  10. package/bajo/method/record/update.js +1 -1
  11. package/bajo/method/sanitize/date.js +1 -1
  12. package/bajo/method/stat/histogram.js +1 -1
  13. package/bajo/method/validate.js +1 -1
  14. package/bajo/start.js +1 -1
  15. package/bajoCli/applet/connection.js +4 -4
  16. package/bajoCli/applet/lib/post-process.js +5 -5
  17. package/bajoCli/applet/model-clear.js +1 -1
  18. package/bajoCli/applet/model-rebuild.js +14 -14
  19. package/bajoCli/applet/record-create.js +6 -6
  20. package/bajoCli/applet/record-find.js +3 -3
  21. package/bajoCli/applet/record-get.js +1 -1
  22. package/bajoCli/applet/record-remove.js +1 -1
  23. package/bajoCli/applet/record-update.js +8 -8
  24. package/bajoCli/applet/schema.js +4 -4
  25. package/bajoCli/applet/stat-count.js +3 -3
  26. package/bajoI18N/resource/en-US.json +149 -26
  27. package/bajoI18N/resource/id.json +117 -74
  28. package/lib/add-fixtures.js +3 -4
  29. package/lib/build-bulk-action.js +2 -2
  30. package/lib/check-unique.js +2 -2
  31. package/lib/collect-connections.js +2 -2
  32. package/lib/collect-drivers.js +3 -3
  33. package/lib/collect-feature.js +3 -3
  34. package/lib/collect-schemas.js +3 -3
  35. package/lib/generic-prop-sanitizer.js +2 -9
  36. package/lib/mem-db/instantiate.js +1 -1
  37. package/lib/mem-db/method/record/create.js +1 -1
  38. package/lib/mem-db/method/record/get.js +1 -1
  39. package/lib/mem-db/start.js +2 -2
  40. package/lib/resolve-method.js +2 -2
  41. package/lib/sanitize-schema.js +5 -5
  42. package/package.json +1 -1
package/bajo/init.js CHANGED
@@ -6,7 +6,7 @@ import collectSchemas from '../lib/collect-schemas.js'
6
6
  async function checkType (item, items) {
7
7
  const { filter } = this.app.bajo.lib._
8
8
  const existing = filter(items, { type: 'dobo:memory' })
9
- if (existing.length > 1) this.fatal('There could only be one connection type \'%s\'', item.type)
9
+ if (existing.length > 1) this.fatal('onlyOneConnType%s', item.type)
10
10
  }
11
11
 
12
12
  async function init () {
@@ -21,7 +21,7 @@ async function init () {
21
21
  })
22
22
  }
23
23
  this.connections = await buildCollections({ ns: this.name, container: 'connections', handler: collectConnections, dupChecks: ['name', checkType] })
24
- if (this.connections.length === 0) this.log.warn('No %s found!', this.print.write('connection'))
24
+ if (this.connections.length === 0) this.log.warn('notFound%s', this.print.write('connection'))
25
25
  await collectFeature.call(this)
26
26
  await collectSchemas.call(this)
27
27
  }
@@ -5,11 +5,11 @@ async function copyUploaded (name, id, { req, setField, setFile, mimeType, stats
5
5
  name = this.attachmentPreCheck(name)
6
6
  if (!name) {
7
7
  if (silent) return
8
- throw this.error('Name must be provided')
8
+ throw this.error('isMissing%s', this.print.write('field.name'))
9
9
  }
10
10
  if (!this.bajoWeb) {
11
11
  if (silent) return
12
- throw this.error('Plugin \'%s\' is missing')
12
+ throw this.error('missingPlugin%s')
13
13
  }
14
14
  const { dir, files } = await this.bajoWeb.getUploadedFiles(req.id, false, true)
15
15
  const result = []
@@ -5,7 +5,7 @@ async function create (name, id, options = {}) {
5
5
  name = this.attachmentPreCheck(name)
6
6
  if (!name) return
7
7
  const { source, field, file } = options
8
- if (!source) throw this.error('Invalid source')
8
+ if (!source) throw this.error('isMissing%s', this.print.write('field.source'))
9
9
  const baseDir = await this.attachmentGetPath(name, id, field, file, { dirOnly: true })
10
10
  const { fullPath, stats, mimeType, req } = options
11
11
 
@@ -20,7 +20,7 @@ async function create (name, id, options = {}) {
20
20
  file
21
21
  }
22
22
  await mergeAttachmentInfo.call(this, rec, dest, { mimeType, fullPath, stats })
23
- if (req && req.flash) req.flash('notify', req.t('Attachment successfully uploaded'))
23
+ if (req && req.flash) req.flash('notify', req.t('attachmentUploaded'))
24
24
  return rec
25
25
  }
26
26
 
@@ -5,7 +5,7 @@ async function remove (name, id, field, file, options = {}) {
5
5
  const path = await this.attachmentGetPath(name, id, field, file)
6
6
  const { req } = options
7
7
  await fs.remove(path)
8
- if (req && req.flash) req.flash('notify', req.t('Attachment successfully removed'))
8
+ if (req && req.flash) req.flash('notify', req.t('attachmentRemoved'))
9
9
  }
10
10
 
11
11
  export default remove
@@ -3,7 +3,7 @@ function getSchema (input, cloned = true) {
3
3
  let name = isPlainObject(input) ? input.name : input
4
4
  name = this.app.bajo.pascalCase(name)
5
5
  const schema = find(this.schemas, { name })
6
- if (!schema) throw this.error('Unknown model/schema \'%s\'', name)
6
+ if (!schema) throw this.error('unknownModelSchema%s', name)
7
7
  return cloned ? cloneDeep(schema) : schema
8
8
  }
9
9
 
@@ -16,7 +16,7 @@ async function exists (name, thrown, options = {}) {
16
16
  await runHook(`${this.name}.${camelCase(name)}:afterModelExists`, exist, options)
17
17
  await runHook(`${this.name}:afterModelExists`, schema, exist, options)
18
18
  }
19
- if (!exist && thrown) throw this.error('Model doesn\'t exist yet. Please do model rebuild first')
19
+ if (!exist && thrown) throw this.error('modelNotExists%s')
20
20
  cache[name] = exist
21
21
  return exist
22
22
  }
@@ -42,7 +42,7 @@ function buildSort (input, schema, allowSortUnindexed) {
42
42
  if (schema) {
43
43
  const items = keys(sort)
44
44
  each(items, i => {
45
- if (!schema.sortables.includes(i) && !allowSortUnindexed) throw this.error('Sort on unindexed field: \'%s@%s\'', i, schema.name)
45
+ if (!schema.sortables.includes(i) && !allowSortUnindexed) throw this.error('sortOnUnindexedField%s%s', i, schema.name)
46
46
  // if (schema.fullText.fields.includes(i)) throw this.error('Can\'t sort on full-text index: \'%s@%s\'', i, schema.name)
47
47
  })
48
48
  }
@@ -50,7 +50,7 @@ async function create (name, input, opts = {}) {
50
50
  record = await handler.call(this.app[driver.ns], { schema, body: nbody, options })
51
51
  if (options.req) {
52
52
  if (options.req.file) await handleAttachmentUpload.call(this, { name: schema.name, id: body.id, body, options, action: 'create' })
53
- if (options.req.flash && !options.noFlash) options.req.flash('notify', options.req.t('Record successfully created'))
53
+ if (options.req.flash && !options.noFlash) options.req.flash('notify', options.req.t('recordCreated'))
54
54
  }
55
55
  if (!noFeatureHook) await execFeatureHook.call(this, 'afterCreate', { schema, body, record })
56
56
  if (!noHook) {
@@ -20,7 +20,7 @@ async function remove (name, id, opts = {}) {
20
20
  const record = await handler.call(this.app[driver.ns], { schema, id, options })
21
21
  if (options.req) {
22
22
  if (options.req.file) await handleAttachmentUpload.call(this, { name: schema.name, id, options, action: 'remove' })
23
- if (options.req.flash && !options.noFlash) options.req.flash('notify', options.req.t('Record successfully removed'))
23
+ if (options.req.flash && !options.noFlash) options.req.flash('notify', options.req.t('recordRemoved'))
24
24
  }
25
25
  if (!noHook) {
26
26
  await runHook(`${this.name}.${camelCase(name)}:afterRecordRemove`, id, options, record)
@@ -40,7 +40,7 @@ async function update (name, id, input, opts = {}) {
40
40
  const record = await handler.call(this.app[driver.ns], { schema, id, body: nbody, options })
41
41
  if (options.req) {
42
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'))
43
+ if (options.req.flash && !options.noFlash) options.req.flash('notify', options.req.t('recordUpdated'))
44
44
  }
45
45
  if (!noFeatureHook) await execFeatureHook.call(this, 'afterUpdate', { schema, body: nbody, record })
46
46
  if (!noHook) {
@@ -5,7 +5,7 @@ function sanitizeDate (value, { input, output, silent = true } = {}) {
5
5
  const dt = dayjs(value, input)
6
6
  if (!dt.isValid()) {
7
7
  if (silent) return -1
8
- throw this.error('Invalid date')
8
+ throw this.error('invalidDate')
9
9
  }
10
10
  if (output === 'native' || !output) return dt.toDate()
11
11
  return dt.format(output)
@@ -6,7 +6,7 @@ async function histogram (name, filter = {}, options = {}) {
6
6
  const { runHook, join } = this.app.bajo
7
7
  const { dataOnly = true, noHook, type } = options
8
8
  options.dataOnly = false
9
- if (!types.includes(type)) throw this.error('Histogram type must be one of these: %s', join(types))
9
+ if (!types.includes(type)) throw this.error('histogramTypeMusBe%s', join(types))
10
10
  await this.modelExists(name, true)
11
11
  const { handler, schema, driver } = await resolveMethod.call(this, name, 'stat-histogram', options)
12
12
  filter.query = await this.buildQuery({ filter, schema, options }) ?? {}
@@ -150,7 +150,7 @@ async function validate (value, joiSchema, { ns, fields, extFields, params } = {
150
150
  try {
151
151
  return await joiSchema.validateAsync(value, params)
152
152
  } catch (err) {
153
- throw this.error('Validation Error', { details: err.details, values: err.values, ns, statusCode: 422, code: 'DB_VALIDATION' })
153
+ throw this.error('validationError', { details: err.details, values: err.values, ns, statusCode: 422, code: 'DB_VALIDATION' })
154
154
  }
155
155
  }
156
156
 
package/bajo/start.js CHANGED
@@ -12,7 +12,7 @@ async function start (conns = 'all', noRebuild = true) {
12
12
  const schemas = filter(this.schemas, { connection: c.name })
13
13
  const mod = c.type === 'dobo:memory' ? memDbInstantiate : await importModule(`${ns}:/${this.name}/boot/instantiate.js`)
14
14
  await mod.call(this.app[ns], { connection: c, noRebuild, schemas })
15
- this.log.trace('- Driver \'%s:%s\' instantiated', c.driver, c.name)
15
+ this.log.trace('driverInstantiated%s%s', c.driver, c.name)
16
16
  }
17
17
  await memDbStart.call(this)
18
18
  }
@@ -4,18 +4,18 @@ async function connection (path, ...args) {
4
4
  const select = await importPkg('bajoCli:@inquirer/select')
5
5
  const { getOutputFormat, writeOutput } = this.app.bajoCli
6
6
  const format = getOutputFormat()
7
- if (isEmpty(this.connections)) return this.print.fail('No connection found!', { exit: this.app.bajo.applet })
7
+ if (isEmpty(this.connections)) return this.print.fail('notFound%s', 'connection', { exit: this.app.bajo.applet })
8
8
  let name = args[0]
9
9
  if (isEmpty(name)) {
10
10
  const choices = map(this.connections, s => ({ value: s.name }))
11
11
  name = await select({
12
- message: this.print.write('Please choose a connection:'),
12
+ message: this.print.write('chooseConn'),
13
13
  choices
14
14
  })
15
15
  }
16
16
  const result = find(this.connections, { name })
17
- if (!result) return this.print.fail('Can\'t find %s named \'%s\'', this.print.write('connection'), name, { exit: this.app.bajo.applet })
18
- this.print.info('Done!')
17
+ if (!result) return this.print.fail('cantFind%s%s', this.print.write('connection'), name, { exit: this.app.bajo.applet })
18
+ this.print.info('done')
19
19
  await writeOutput(result, path, format)
20
20
  }
21
21
 
@@ -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('No schema found!')
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('Are you sure to continue?'), default: false })
15
+ const answer = await confirm({ message: this.print.write('sureContinue'), default: false })
16
16
  if (!answer) {
17
- this.print.fail('Aborted!')
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('Done!')
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('Error: %s', err.message)
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('No schema found!', { exit: this.app.bajo.applet })
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('No schema found!', { exit: this.app.bajo.applet })
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('Enter schema name(s), separated by space:'),
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('Schema (%d)', names.length), padding: 0.5, borderStyle: 'round' }))
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('The above mentioned schema(s) will be rebuilt as model. Continue?'),
24
+ message: this.print.write('schemasWillBeRebuiltContinue'),
25
25
  default: false
26
26
  })
27
- if (!answer) return this.print.fail('Aborted!', { exit: this.app.bajo.applet })
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('Rebuilding \'%s\'...', schema.name)
39
+ const spin = this.print.spinner({ showCounter: true }).start('rebuilding%s', schema.name)
40
40
  if (!instance) {
41
- spin.warn('Client instance not connected \'%s@%s\'. Skipped!', schema.connection, schema.name)
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('Model \'%s\' successfully dropped', schema.name)
50
+ spin.setText('modelDropped%s', schema.name)
51
51
  } catch (err) {
52
- spin.fail('Error on dropping model \'%s\': %s', schema.name, err.message)
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('Model \'%s\' exists. Won\'t rebuild without --force', schema.name)
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('Model \'%s\' successfully created', schema.name)
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('Model \'%s\' successfully created, with fixture: added %d, rejected: %s', schema.name, fixture.success, fixture.failed)
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('Error on creating \'%s\': %s', schema.name, err.message)
72
+ spin.fail('errorCreatingModel%s%s', schema.name, err.message)
73
73
  result.failed++
74
74
  }
75
75
  }
76
- this.print.info('Done! Succeded: %d, failed: %s, skipped: %d', result.succed, result.failed, result.skipped)
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('No schema found!', { exit: this.app.bajo.applet })
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('Please select a schema:'),
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('Enter JSON payload:'),
18
+ message: this.print.write('enterJsonPayload'),
19
19
  validate: text => {
20
- if (isEmpty(text)) return this.print.write('Payload is required')
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('Payload must be a valid JSON object')
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('Invalid payload syntax', { exit: this.app.bajo.applet })
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('No schema found!', { exit: this.app.bajo.applet })
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('Please select a schema:'),
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('Please enter a query (if any):')
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('No schema found!', { exit: this.app.bajo.applet })
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('No schema found!', { exit: this.app.bajo.applet })
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('No schema found!', { exit: this.app.bajo.applet })
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('Please select a schema:'),
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('Enter record ID:'),
19
- validate: text => isEmpty(text) ? this.print.write('ID is required') : true
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('Enter JSON payload:'),
24
+ message: this.print.write('enterJsonPayload'),
25
25
  validate: text => {
26
- if (isEmpty(text)) return this.print.write('Payload is required')
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('Payload must be a valid JSON object')
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('Invalid payload syntax', { exit: this.app.bajo.applet })
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' })
@@ -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('No schema found!', { exit: this.app.bajo.applet })
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('Please choose a schema:'),
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('Can\'t find %s named \'%s\'', this.print.write('schema'), name, { exit: this.app.bajo.applet })
18
- this.print.info('Done!')
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('No schema found!', { exit: this.app.bajo.applet })
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('Please select a schema:'),
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('Please enter a query (if any):')
17
+ message: this.print.write('enterQueryIfAny')
18
18
  })
19
19
  }
20
20
  const filter = { query }
@@ -1,4 +1,122 @@
1
1
  {
2
+ "isConnected%s%s": "[%s] '%s' is connected",
3
+ "errorOn%s%s": "[%s] Error on '%s': %s",
4
+ "isDestroyed%s%s": "[%s] '%s' is destroyed",
5
+ "loadedSchemas%s": "[%s] Loaded schemas: %s",
6
+ "loadSchema%s%s%d": "[%s] Load schema: %s (%d)",
7
+ "loadedConns%s%s": "[%s] Loaded connections: %s",
8
+ "unsupportedPropTypeIn%s%s": "Unsupported property type '%s' in '%s'",
9
+ "noSchemaFound": "No schema found!",
10
+ "enterSchemaName": "Enter schema name, separated by space:",
11
+ "noSchemaMatched": "No schema matched",
12
+ "schema%d": "Schema (%d)",
13
+ "schemasWillBeRebuiltContinue": "The above mentioned schema(s) will be rebuilt as model. Continue?",
14
+ "rebuilding%s": "Rebuilding '%s'...",
15
+ "noDbConn%s%s": "No DB connection '%s' for '%s'. Aborted!",
16
+ "errorDroppingModel%s%s": "Error dropping model '%s': %s",
17
+ "modelExistsNeedForce%s": "Model '%s' exists already. Can't rebuild without --force",
18
+ "modelCreated%s": "Model '%s' successfully created",
19
+ "modelCreatedWithFixture%s%s%s": "Model '%s' successfully created, with fixture: added %s, rejected: %s",
20
+ "errorCreatingModel%s%s": "Error creating model '%s': %s",
21
+ "modelDropped%s": "Model '%s' successfully dropped",
22
+ "memoryDbSkipped%s%s": "DB '%s' for '%s' is a memory DB, skipped",
23
+ "modelBuiltOnthefly%s%s%s": "[%s] Model '%s@%s' successfully built on the fly",
24
+ "unableToBuildModel%s%s%s": "Unable to re-build model '%s' in '%s': %s",
25
+ "unknownSchema%s": "Unknown schema '%s'",
26
+ "payloadMustBeJson": "Payload must be a valid JSON",
27
+ "selectSchema": "Please select a schema:",
28
+ "enterJsonPayload": "Enter JSON payload:",
29
+ "payloadRequired": "Payload is required",
30
+ "invalidPayloadSyntax": "Invalid payload syntax",
31
+ "creatingRecord": "Creating record",
32
+ "enterRecordId:": "Enter record ID:",
33
+ "idIsRequired": "ID is required",
34
+ "gettingRecord": "Getting record",
35
+ "removingRecord": "Deleting record",
36
+ "cantFindSchema%s": "Can't find schema named %s",
37
+ "cantFind%s%s": "Can't find %s named %s",
38
+ "recordNotFound%s%s": "Record '%s@%s' not found",
39
+ "invalidSchema%s": "Invalid schema '%s'",
40
+ "noPropsFoundOnSchema%s": "Schema '%s' doesn't have any property at all",
41
+ "fieldIdReserved%s": "Field 'id@%s' is a reserved column and should not added manually",
42
+ "missingPropType%s%s": "Property type for '%s@%s' is missing",
43
+ "unsupportedPropType%s%s%s": "Unsupported property type '%s@%s' in '%s'",
44
+ "unknownConn%s%s": "Unknown connection '%s@%s'",
45
+ "fieldIsRequired%s%s": "Column '%s@%s' is required",
46
+ "keyIsRequired%s": "Key '%s' is required",
47
+ "enterQueryIfAny": "Please enter your query (if any):",
48
+ "findingRecords": "Finding records",
49
+ "recordExists%s%s": "Record '%s@%s' exists already",
50
+ "fieldGroupAggregateMissing": "Field to group aggregate is missing",
51
+ "fieldCalcAggregateMissing": "Field to calculate aggregate is missing",
52
+ "baseFieldForHistogramMissing": "Base field for histogram must be provided",
53
+ "unknownBaseFieldForHistogram%s": "Unknown base field for histogram '%s'",
54
+ "fieldTypeMustBeDatetime%s%s": "Field type '%s@%s' must be a datetime field",
55
+ "groupFieldToAggregateMissing": "Group field to aggregate is missing",
56
+ "unknownGroupField%s%s": "Unknown group field '%s@%s'",
57
+ "grupFieldMustBeNumber": "Group field must be of type integer, smallint or float",
58
+ "unsupportedAggregateType%s": "Unsupported aggregate type: '%s'",
59
+ "keyIsRequired%s%s": "'%s@%s' key is required",
60
+ "fulltextNeedIntegerId%s%s": "Full text index need integer type primary id in '%s@%s'",
61
+ "unsupportedAggregate%s": "Unsupported aggregate '%s'",
62
+ "unsupportedAllowedChoices%s%s%s%s%s": "Unsupported %s '%s' for '%s@%s'. Allowed choices: %s",
63
+ "methodIsDisabled%s%s": "Method '%s@%s' is disabled",
64
+ "invalidModelForPersistence%s": "Invalid model for persistence: %s",
65
+ "cantLoad%s%s": "Can't load %s: %s",
66
+ "noRecordFound": "No record found",
67
+ "recordsFound%d": "%d record(s) found",
68
+ "add": "Add",
69
+ "edit": "Edit",
70
+ "delete": "Delete",
71
+ "export": "Export",
72
+ "query": "Query",
73
+ "queryBuilder": "Query Builder",
74
+ "list": "List",
75
+ "submitQuery": "Submit Query",
76
+ "dataExport": "Data Export",
77
+ "recordCreated": "Record successfully created",
78
+ "recordRemoved": "Record successfully removed",
79
+ "recordUpdated": "Record successfully updated",
80
+ "attachmentUploaded": "Attachment successfully uploaded",
81
+ "attachmentRemoved": "Attachment successfully removed",
82
+ "unknownModelSchema%s": "Unknown model/schema '%s'",
83
+ "sortOnUnindexedField%s%s": "Sort on unindexed field: '%s@%s'",
84
+ "modelNotExists%s": "Model '%s' doesn't exist yet. Please do model rebuild first",
85
+ "invalidDate": "Invalid date",
86
+ "histogramTypeMusBe%s": "Histogram type must be one of these: %s",
87
+ "methodUnsupported%s%s": "Method '%s@%s' is unsupported",
88
+ "uniqueConstraintError": "Unique constraint error",
89
+ "taskMustHaveModel%s": "Task must have %s model",
90
+ "driverNotInstalled%s": "Problem with '%s' driver file. Not installed yet?",
91
+ "generalDbError": "General Database Error",
92
+ "dbConstrainError": "Database Constraint Error",
93
+ "onlySupportThese%s": "Only support one of these: %s",
94
+ "isMissing%s": "%s is missing",
95
+ "notFound%s": "No %s found!",
96
+ "clientInstanceNotConnected%s": "Client instance not connected '%s@%s'. Skipped!",
97
+ "proxiedConnBound%s": "'%s' is bound to a proxied connection, skipped!'",
98
+ "addingMemoryPersistenceIgnored": "'%s' is a memory persistence model. Adding records from fixture is ignored!",
99
+ "onlyOneConnType%s": "There could only be one connection type '%s'",
100
+ "mustValidDbType": "Connection must have a valid DB type",
101
+ "unsupportedDbType%s": "Unsupported DB type '%s'",
102
+ "driverMustProvideDbType": "A DB driver must provide at least one database type",
103
+ "driverMustHaveName": "A DB driver must have a driver name",
104
+ "dbTypeAlreadySupportedByDriver%s%s": "Database type '%s' already supported by driver '%s'",
105
+ "featureNotAsync%s": "Feature '%s' should be an async function",
106
+ "unsupportedIndexType%s%s%s%s": "Unsupported index type %s for '%s@%s'. Allowed choices: %s",
107
+ "unknownFeature%s%s": "'Unknown feature '%s@%s'",
108
+ "onlyAccepFields%s%s": "Only accept array of field names or single string of field name '%s@%s'",
109
+ "invalidFieldName%s%s": "Invalid field name '%s@%s'",
110
+ "error%s": "Error: %s",
111
+ "succeedFailSkip%d%d%d": "Done! Succeded: %d, failed: %s, skipped: %d",
112
+ "chooseConn": "Please choose a connection:",
113
+ "sureContinue": "Are you sure to continue?",
114
+ "loadingDbFeature": "Loading DB feature",
115
+ "totalLoadedFeatures%d": "Total loaded features: %d",
116
+ "loadingDbSchemas": "Loading DB schemas",
117
+ "addingFixtureToMemDb": "Adding fixture for memory database",
118
+ "recordsAdded%s%d%d": "%s: %d of %d records added",
119
+ "driverInstantiated%s%s": "- Driver '%s:%s' instantiated",
2
120
  "field": {
3
121
  "id": "ID",
4
122
  "code": "Kode",
@@ -61,32 +179,37 @@
61
179
  "cycle": "Cycle",
62
180
  "default": "Default"
63
181
  },
182
+ "validationError": "Kesalahan Validasi",
64
183
  "validation": {
65
- "any.required": "Required",
66
- "any.only": "Must match with {{ref}}",
67
- "string.alphanum": "Must only contain alpha-numeric characters",
68
- "string.base": "Must be a string",
69
- "string.base64": "Must be a valid base64 string",
70
- "string.creditCard": "Must be a credit card",
71
- "string.dataUri": "Must be a valid dataUri string",
72
- "string.domain": "Must contain a valid domain name",
73
- "string.email": "Must be a valid email",
74
- "string.empty": "Required",
75
- "string.guid": "Must be a valid GUID",
76
- "string.hex": "Must only contain hexadecimal characters",
77
- "string.hexAlign": "Hex decoded representation must be byte aligned",
78
- "string.hostname": "Must be a valid hostname",
79
- "string.ip": "must be a valid ip address with a {{cidr}} CIDR",
80
- "string.ipVersion": "Must be a valid ip address of one of the following versions {{version}} with a {{cidr}} CIDR",
81
- "string.isoDate": "Must be in iso format",
82
- "string.isoDuration": "Must be a valid ISO 8601 duration",
83
- "string.length": "Length must be {{limit}} characters long",
84
- "string.lowercase": "Must only contain lowercase characters",
85
- "string.max": "Length must be less than or equal to {{limit}} characters long",
86
- "string.min": "Length must be at least {{limit}} characters long",
87
- "string.token": "Must only contain alpha-numeric and underscore characters",
88
- "string.trim": "Must not have leading or trailing whitespace",
89
- "string.uri": "Must be a valid uri",
90
- "string.uppercase": "Must only contain uppercase characters"
184
+ "any": {
185
+ "required": "Required",
186
+ "only": "Must match with {{ref}}"
187
+ },
188
+ "string": {
189
+ "alphanum": "Must only contain alpha-numeric characters",
190
+ "base": "Must be a string",
191
+ "base64": "Must be a valid base64 string",
192
+ "creditCard": "Must be a credit card",
193
+ "dataUri": "Must be a valid dataUri string",
194
+ "domain": "Must contain a valid domain name",
195
+ "email": "Must be a valid email",
196
+ "empty": "Required",
197
+ "guid": "Must be a valid GUID",
198
+ "hex": "Must only contain hexadecimal characters",
199
+ "hexAlign": "Hex decoded representation must be byte aligned",
200
+ "hostname": "Must be a valid hostname",
201
+ "ip": "must be a valid ip address with a {{cidr}} CIDR",
202
+ "ipVersion": "Must be a valid ip address of one of the following versions {{version}} with a {{cidr}} CIDR",
203
+ "isoDate": "Must be in iso format",
204
+ "isoDuration": "Must be a valid ISO 8601 duration",
205
+ "length": "Length must be {{limit}} characters long",
206
+ "lowercase": "Must only contain lowercase characters",
207
+ "max": "Length must be less than or equal to {{limit}} characters long",
208
+ "min": "Length must be at least {{limit}} characters long",
209
+ "token": "Must only contain alpha-numeric and underscore characters",
210
+ "trim": "Must not have leading or trailing whitespace",
211
+ "uri": "Must be a valid uri",
212
+ "uppercase": "Must only contain uppercase characters"
213
+ }
91
214
  }
92
215
  }
@@ -1,77 +1,120 @@
1
1
  {
2
- "[%s] '%s' is connected": "[%s] '%s' telah tersambung",
3
- "[%s] Error on '%s': %s": "[%s] Kesalahan pada '%s': %s",
4
- "[%s] '%s' is destroyed": "[%s] '%s' telah dimusnahkan",
5
- "[%s] Loaded schemas: %s": "[%s] Skema termuat: %s",
6
- "[%s] Load schema: %s (%d)": "[%s] Muat skema: %s (%d)",
7
- "[%s] Loaded connections: %s": "[%s] Koneksi termuat: %s",
8
- "Unsupported property type '%s' in '%s'": "Tipe properti '%s' di '%s' tidak didukung",
9
- "No schema found!": "Tidak ditemukan skema!",
10
- "Enter schema name(s), separated by space:": "Masukkan nama skema, dipisah dengan spasi:",
11
- "No schema matched": "Tidak ditemukan skema yang cocok",
12
- "Schema (%d)": "Skema (%d)",
13
- "The above mentioned schema(s) will be rebuilt & modeled. Continue?": "Semua skema tersebut diatas akan dibuat ulang sebagai model. Anda yakin?",
14
- "Rebuilding '%s'...": "Pembuatan ulang '%s'...",
15
- "No database connection '%s' for '%s'. Aborted!'": "Tidak ada koneksi database '%s' untuk '%s'. Batalkan!",
16
- "Error on dropping model '%s': %s": "Gagal menghapus model '%s': %s",
17
- "Model '%s' exists. Won't rebuild without --force": "Model '%s' telah ada. Tidak dilakukan pembuatan ulang tanpa --force",
18
- "Model '%s' successfully created": "Model '%s' sukses dibuat",
19
- "Error on creating model '%s': %s": "Gagal membuat model '%s': %s",
20
- "Model '%s' successfully dropped": "Model '%s' sukses dihapus",
21
- "Db '%s' for '%s' is a memory database, skipped": "Db '%s' untuk '%s' adalah database memori, lewati",
22
- "[%s] Model '%s@%s' successfully built on the fly": "[%s] Model '%s@%s' sukses dibuat ulang on the fly",
23
- "Unable to build model '%s@%s': %s": "Gagal membuat ulang model '%s' di '%s': %s",
24
- "Unknown schema '%s'": "Skema '%s' tidak dikenal",
25
- "Payload must be a valid JSON object": "Data harus berupa obyek JSON yang valid",
26
- "Please select a schema:": "Silahkan masukkan sebuah skema:",
27
- "Enter JSON payload:": "Masukkan data JSON:",
28
- "Payload is required": "Data harus diisi",
29
- "Invalid payload syntax": "Sintak data tidak valid",
30
- "Creating record": "Pembuatan data",
31
- "Enter record ID:": "Masukkan ID data:",
32
- "ID is required": "ID harus diisi",
33
- "Getting record": "Mengambil data",
34
- "Removing record": "Menghapus data",
35
- "Can't find schema named %s": "Tidak bisa menemukan skema dengan nama %s",
36
- "Record '%s@%s' not found!": "Data '%s@%s' tidak ditemukan",
37
- "Invalid schema '%s'": "Skema '%s' tidak valid",
38
- "Schema '%s' doesn't have properties at all": "Skema '%s' tidak memiliki properti sama sekali",
39
- "Field 'id@%s' is a reserved field and should not be added manually": "Kolom 'id@%s' adalah kolom ter-reservasi dan seharusnya tidak ditambahkan secara manual",
40
- "Missing property type for '%s@%s'": "Tipe properti untuk '%s@%s' tidak ditemukan",
41
- "Unsupported property type '%s@%s' in '%s'": "Tipe properti '%s@%s' di '%s' tidak didukung",
42
- "Unknown connection '%s@%s'": "Koneksi '%s@%s' tidak dikenal",
43
- "Field '%s@%s' is required": "Kolom '%s@%s' harus diisi",
44
- "'%s' key is required": "Kunci '%s' harus diisi",
45
- "Please enter a query (if any):": "Silahkan masukkan kueri (jika ada):",
46
- "Finding record(s)": "Temukan data",
47
- "Record '%s@%s' exists already!": "Data '%s@%s' sudah ada",
48
- "Field to group aggregate is missing": "Field to group aggregate is missing",
49
- "Field to calculate aggregate is missing": "Field to calculate aggregate is missing",
50
- "Base field for histogram must be provided": "Base field for histogram must be provided",
51
- "Unknown base field for histogram '%s'": "Unknown base field for histogram '%s'",
52
- "Field type '%s@%s' must be a datetime field": "Field type '%s@%s' must be a datetime field",
53
- "Group field to aggregate is missing": "Group field to aggregate is missing",
54
- "Unknown group field '%s@%s'": "Unknown group field '%s@%s'",
55
- "Group field must be of type integer, smallint or float": "Group field must be of type integer, smallint or float",
56
- "Unsupported aggregate type: '%s'": "Unsupported aggregate type: '%s'",
57
- "'%s@%s' key is required": "'%s@%s' key is required",
58
- "Full text index need integer type primary id in '%s@%s'": "Full text index need integer type primary id in '%s@%s'",
59
- "Unsupported aggregate '%s'": "Unsupported aggregate '%s'",
60
- "Unsupported %s '%s' for '%s@%s'. Allowed choices: %s": "Unsupported %s '%s' for '%s@%s'. Allowed choices: %s",
61
- "Method '%s@%s' is disabled": "Metode '%s@%s' dinonaktifkan",
62
- "Invalid model for persistence: %s": "Model untuk penyimpanan tidak valid: %s",
63
- "Can't load %s: %s": "Tidak bisa memuat %s: %s",
64
- "No record found": "Tidak ditemukan data",
65
- "%d record(s) found": "Ditemukan %d data",
66
- "Add": "Tambah",
67
- "Edit": "Ubah",
68
- "Delete": "Hapus",
69
- "Export": "Ekspor",
70
- "Query": "Kueri",
71
- "Query Builder": "Pembuat Kueri",
72
- "List": "Daftar",
73
- "Submit Query": "Kirim Kueri",
74
- "Data Export": "Ekspor Data",
2
+ "isConnected%s%s": "[%s] '%s' telah tersambung",
3
+ "errorOn%s%s": "[%s] Kesalahan pada '%s': %s",
4
+ "isDestroyed%s%s": "[%s] '%s' telah dimusnahkan",
5
+ "loadedSchemas%s": "[%s] Skema termuat: %s",
6
+ "loadSchema%s%s%d": "[%s] Muat skema: %s (%d)",
7
+ "loadedConns%s%s": "[%s] Koneksi termuat: %s",
8
+ "unsupportedPropTypeIn%s%s": "Tipe properti '%s' di '%s' tidak didukung",
9
+ "noSchemaFound": "Tidak ditemukan skema!",
10
+ "enterSchemaName": "Masukkan nama skema, dipisah dengan spasi:",
11
+ "noSchemaMatched": "Tidak ditemukan skema yang cocok",
12
+ "schema%d": "Skema (%d)",
13
+ "schemasWillBeRebuiltContinue": "Semua skema tersebut diatas akan dibuat ulang sebagai model. Anda yakin?",
14
+ "rebuilding%s": "Pembuatan ulang '%s'...",
15
+ "noDbConn%s%s": "Tidak ada koneksi database '%s' untuk '%s'. Batalkan!",
16
+ "errorDroppingModel%s%s": "Gagal menghapus model '%s': %s",
17
+ "modelExistsNeedForce%s": "Model '%s' telah ada. Tidak dilakukan pembuatan ulang tanpa --force",
18
+ "modelCreated%s": "Model '%s' sukses dibuat",
19
+ "errorCreatingModel%s%s": "Gagal membuat model '%s': %s",
20
+ "modelDropped%s": "Model '%s' sukses dihapus",
21
+ "memoryDbSkipped%s%s": "Db '%s' untuk '%s' adalah database memori, lewati",
22
+ "modelBuiltOnthefly%s%s%s": "[%s] Model '%s@%s' sukses dibuat ulang on the fly",
23
+ "unableToBuildModel%s%s%s": "Gagal membuat ulang model '%s' di '%s': %s",
24
+ "unknownSchema%s": "Skema '%s' tidak dikenal",
25
+ "payloadMustBeJson": "Data harus berupa obyek JSON yang valid",
26
+ "selectSchema": "Silahkan masukkan sebuah skema:",
27
+ "enterJsonPayload": "Masukkan data JSON:",
28
+ "payloadRequired": "Data harus diisi",
29
+ "invalidPayloadSyntax": "Sintak data tidak valid",
30
+ "creatingRecord": "Pembuatan data",
31
+ "enterRecordId:": "Masukkan ID data:",
32
+ "idIsRequired": "ID harus diisi",
33
+ "gettingRecord": "Mengambil data",
34
+ "removingRecord": "Menghapus data",
35
+ "cantFindSchema%s": "Tidak bisa menemukan skema dengan nama %s",
36
+ "recordNotFound%s%s": "Data '%s@%s' tidak ditemukan",
37
+ "invalidSchema%s": "Skema '%s' tidak valid",
38
+ "noPropsFoundOnSchema%s": "Skema '%s' tidak memiliki properti sama sekali",
39
+ "fieldIdReserved%s": "Kolom 'id@%s' adalah kolom ter-reservasi dan seharusnya tidak ditambahkan secara manual",
40
+ "missingPropType%s%s": "Tipe properti untuk '%s@%s' tidak ditemukan",
41
+ "unsupportedPropType%s%s%s": "Tipe properti '%s@%s' di '%s' tidak didukung",
42
+ "unknownConn%s%s": "Koneksi '%s@%s' tidak dikenal",
43
+ "fieldIsRequired%s%s": "Kolom '%s@%s' harus diisi",
44
+ "keyIsRequired%s": "Kunci '%s' harus diisi",
45
+ "enterQueryIfAny": "Silahkan masukkan kueri (jika ada):",
46
+ "findingRecords": "Temukan data",
47
+ "recordExists%s%s": "Data '%s@%s' sudah ada",
48
+ "fieldGroupAggregateMissing": "Field to group aggregate is missing",
49
+ "fieldCalcAggregateMissing": "Field to calculate aggregate is missing",
50
+ "baseFieldForHistogramMissing": "Base field for histogram must be provided",
51
+ "unknownBaseFieldForHistogram%s": "Unknown base field for histogram '%s'",
52
+ "fieldTypeMustBeDatetime%s%s": "Field type '%s@%s' must be a datetime field",
53
+ "groupFieldToAggregateMissing": "Group field to aggregate is missing",
54
+ "unknownGroupField%s%s": "Unknown group field '%s@%s'",
55
+ "grupFieldMustBeNumber": "Group field must be of type integer, smallint or float",
56
+ "unsupportedAggregateType%s": "Unsupported aggregate type: '%s'",
57
+ "keyIsRequired%s%s": "'%s@%s' key is required",
58
+ "fulltextNeedIntegerId%s%s": "Full text index need integer type primary id in '%s@%s'",
59
+ "unsupportedAggregate%s": "Unsupported aggregate '%s'",
60
+ "unsupportedAllowedChoices%s%s%s%s%s": "Unsupported %s '%s' for '%s@%s'. Allowed choices: %s",
61
+ "methodIsDisabled%s%sMethod": "Metode '%s@%s' dinonaktifkan",
62
+ "invalidModelForPersistence%s": "Model untuk penyimpanan tidak valid: %s",
63
+ "cantLoad%s%s": "Tidak bisa memuat %s: %s",
64
+ "noRecordFound": "Tidak ditemukan data",
65
+ "recordsFound%d": "Ditemukan %d data",
66
+ "add": "Tambah",
67
+ "edit": "Ubah",
68
+ "delete": "Hapus",
69
+ "export": "Ekspor",
70
+ "query": "Kueri",
71
+ "queryBuilder": "Pembuat Kueri",
72
+ "list": "Daftar",
73
+ "submitQuery": "Kirim Kueri",
74
+ "dataExport": "Ekspor Data",
75
+ "recordCreated": "Record successfully created",
76
+ "recordRemoved": "Record successfully removed",
77
+ "recordUpdated": "Record successfully updated",
78
+ "attachmentUploaded": "Attachment successfully uploaded",
79
+ "attachmentRemoved": "Attachment successfully removed",
80
+ "unknownModelSchema%s": "Unknown model/schema '%s'",
81
+ "sortOnUnindexedField%s%s": "Sort on unindexed field: '%s@%s'",
82
+ "modelNotExists%s": "Model '%s' doesn't exist yet. Please do model rebuild first",
83
+ "invalidDate": "Invalid date",
84
+ "histogramTypeMusBe%s": "Histogram type must be one of these: %s",
85
+ "methodUnsupported%s%s": "Method '%s@%s' is unsupported",
86
+ "uniqueConstraintError": "Unique constraint error",
87
+ "taskMustHaveModel%s": "Task must have %s model",
88
+ "driverNotInstalled%s": "Problem with '%s' driver file. Not installed yet?",
89
+ "generalDbError": "General Database Error",
90
+ "dbConstrainError": "Database Constraint Error",
91
+ "onlySupportThese%s": "Only support one of these: %s",
92
+ "isMissing%s": "%s is missing",
93
+ "notFound%s": "No %s found!",
94
+ "clientInstanceNotConnected%s": "Client instance not connected '%s@%s'. Skipped!",
95
+ "proxiedConnBound%s": "'%s' is bound to a proxied connection, skipped!'",
96
+ "addingMemoryPersistenceIgnored": "'%s' is a memory persistence model. Adding records from fixture is ignored!",
97
+ "onlyOneConnType%s": "There could only be one connection type '%s'",
98
+ "mustValidDbType": "Connection must have a valid DB type",
99
+ "unsupportedDbType%s": "Unsupported DB type '%s'",
100
+ "driverMustProvideDbType": "A DB driver must provide at least one database type",
101
+ "driverMustHaveName": "A DB driver must have a driver name",
102
+ "dbTypeAlreadySupportedByDriver%s%s": "Database type '%s' already supported by driver '%s'",
103
+ "featureNotAsync%s": "Feature '%s' should be an async function",
104
+ "unsupportedIndexType%s%s%s%s": "Unsupported index type %s for '%s@%s'. Allowed choices: %s",
105
+ "unknownFeature%s%s": "'Unknown feature '%s@%s'",
106
+ "onlyAccepFields%s%s": "Only accept array of field names or single string of field name '%s@%s'",
107
+ "invalidFieldName%s%s": "Invalid field name '%s@%s'",
108
+ "error%s": "Error: %s",
109
+ "succeedFailSkip%d%d%d": "Done! Succeded: %d, failed: %s, skipped: %d",
110
+ "chooseConn": "Please choose a connection:",
111
+ "sureContinue": "Are you sure to continue?",
112
+ "loadingDbFeature": "Loading DB feature",
113
+ "totalLoadedFeatures%d": "Total loaded features: %d",
114
+ "loadingDbSchemas": "Loading DB schemas",
115
+ "addingFixtureToMemDb": "Adding fixture for memory database",
116
+ "recordsAdded%s%d%d": "%s: %d of %d records added",
117
+ "driverInstantiated%s%s": "- Driver '%s:%s' instantiated",
75
118
  "field": {
76
119
  "id": "ID",
77
120
  "code": "Kode",
@@ -134,7 +177,7 @@
134
177
  "cycle": "Cycle",
135
178
  "default": "Default"
136
179
  },
137
- "Validation Error": "Kesalahan Validasi",
180
+ "validationError": "Kesalahan Validasi",
138
181
  "validation": {
139
182
  "any": {
140
183
  "required": "Harus diisi/dipilih",
@@ -1,11 +1,11 @@
1
1
  import path from 'path'
2
2
 
3
3
  async function addFixture (name, { spinner } = {}) {
4
- const { resolvePath, readConfig, eachPlugins, getPluginDataDir } = this.app.bajo
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('\'%s\' is bound to a proxied connection, skipped!', schema.name)
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: %d of %d records added', schema.name, result.success, items.length)
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
  }
@@ -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('Method \'%s:%s\' is disabled', camelCase('bulk ' + action), name)
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('Method \'%s:%s\' is unsupported', camelCase('bulk ' + action), name)
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
  }
@@ -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: 'Unique constraint error', value: id }]
15
- throw this.error('Unique constraint error', { details })
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('Connection must have a valid DB type')
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('Unsupported DB type \'%s\'', conn.type)
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`
@@ -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('A DB driver must provide at least one database type')
18
- if (!info.driver) this.fatal('A DB driver must have a driver name')
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('Database type \'%s\' already supported by driver \'%s\'', type, info.driver)
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,
@@ -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('Feature \'%s\' should be an async function', name)
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('Loading DB feature')
19
+ this.log.trace('loadingDbFeature')
20
20
  await eachPlugins(handler, { glob: 'feature/*.js', prefix: this.name })
21
- this.log.debug('Total loaded features: %d', Object.keys(this.feature).length)
21
+ this.log.debug('totalLoadedFeatures%d', Object.keys(this.feature).length)
22
22
  }
23
23
 
24
24
  export default collectFeature
@@ -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('Invalid schema \'%s\'', defName)
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('Schema \'%s\' doesn\'t have properties at all', mod.name)
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('No %s found!', this.print.write('schema'))
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('Unsupported %s \'%s\' for \'%s@%s\'. Allowed choices: %s',
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('Unsupported index type %s for \'%s@%s\'. Allowed choices: %s',
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('Can\'t load %s: %s', schema.name, err.message)
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('Record \'%s@%s\' exists already!', body.id, schema.name)
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('Record \'%s@%s\' not found!', id, schema.name, { statusCode: 404 })
5
+ if (!result && thrownNotFound) throw this.error('recordNotFound%s%s', id, schema.name, { statusCode: 404 })
6
6
  return { data: result }
7
7
  }
8
8
 
@@ -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('Adding fixture for memory database')
12
+ this.log.debug('addingFixtureToMemDb')
13
13
  for (const schema of schemas) {
14
14
  if (schema.persistence) {
15
- this.log.warn('\'%s\' is a memory persistence model. Adding records from fixture is ignored!', schema.name)
15
+ this.log.warn('addingMemoryPersistenceIgnored', schema.name)
16
16
  continue
17
17
  }
18
18
  let { success, error } = await addFixtures.call(this, schema.name)
@@ -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('Method \'%s@%s\' is disabled', camelCase(method), name)
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('Method \'%s@%s\' is unsupported', camelCase(method), name)
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
  }
@@ -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('Unknown feature \'%s@%s\'', f.name, item.name)
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('Only accept array of field names or single string of field name \'%s@%s\'', 'indexes', item.name)
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('Invalid field name \'%s@%s\'', f, item.name)
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('Loading DB schemas')
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('Loaded schemas: %s', join(map(this.schemas, 'name')))
190
+ this.log.debug('loadedSchemas%s', join(map(this.schemas, 'name')))
191
191
  }
192
192
 
193
193
  export default sanitizeSchema
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dobo",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
4
4
  "description": "Database ORM/ODM for Bajo Framework",
5
5
  "main": "index.js",
6
6
  "scripts": {