bajo 1.0.4 → 1.0.5

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 (33) hide show
  1. package/bajo/intl/en-US.json +136 -0
  2. package/bajo/intl/id.json +136 -0
  3. package/boot/class/app.js +1 -2
  4. package/boot/class/bajo-core/helper/attach-method.js +1 -1
  5. package/boot/class/bajo-core/helper/boot-order.js +3 -3
  6. package/boot/class/bajo-core/helper/build-config.js +16 -2
  7. package/boot/class/bajo-core/helper/exit-handler.js +3 -3
  8. package/boot/class/bajo-core/helper/run-as-applet.js +4 -4
  9. package/boot/class/bajo-core/method/break-ns-path.js +1 -1
  10. package/boot/class/bajo-core/method/build-collections.js +4 -4
  11. package/boot/class/bajo-core/method/format.js +36 -0
  12. package/boot/class/bajo-core/method/get-global-module-dir.js +2 -2
  13. package/boot/class/bajo-core/method/get-method.js +1 -1
  14. package/boot/class/bajo-core/method/get-plugin.js +1 -1
  15. package/boot/class/bajo-core/method/import-pkg.js +1 -1
  16. package/boot/class/bajo-core/method/parse-object.js +8 -6
  17. package/boot/class/bajo-core/method/read-config.js +3 -3
  18. package/boot/class/bajo-core/method/read-json.js +1 -1
  19. package/boot/class/bajo-core/method/run-hook.js +1 -1
  20. package/boot/class/bajo-core/method/save-as-download.js +1 -1
  21. package/boot/class/bajo-plugin/helper/attach-method.js +1 -1
  22. package/boot/class/bajo-plugin/helper/build-config.js +5 -2
  23. package/boot/class/bajo-plugin/helper/check-clash.js +3 -3
  24. package/boot/class/bajo-plugin/helper/check-dependency.js +3 -3
  25. package/boot/class/bajo-plugin/helper/collect-exit-handlers.js +1 -1
  26. package/boot/class/bajo-plugin/helper/collect-hooks.js +1 -1
  27. package/boot/class/bajo-plugin/helper/run.js +1 -1
  28. package/boot/class/log.js +3 -3
  29. package/boot/class/plugin.js +2 -1
  30. package/boot/class/print.js +40 -6
  31. package/boot/lib/read-all-configs.js +2 -2
  32. package/package.json +1 -1
  33. package/bajoI18N/resource/id.json +0 -31
@@ -0,0 +1,136 @@
1
+ {
2
+ "packageNotFoundOrNotBajo%s": "Package '%s' not found or isn't a valid Bajo package",
3
+ "unknownPluginOrNotLoaded%s": "Unknown plugin '%s' or plugin isn't loaded yet",
4
+ "collectionExists%s": "Collection '%s' already exists",
5
+ "cantLocateNpmGlobalDir": "Can't locate npm global module directory",
6
+ "cantLocateGlobalDir%s": "Can't locate '%s' global module directory",
7
+ "cantFindMethod%s": "Can't find method named '%s'",
8
+ "pluginWithALiasNotLoaded%s": "Plugin with alias '%s' is not loaded",
9
+ "cantFind%s": "Can't find %s",
10
+ "dtUnparsable%s": "Date/time unparsable '%s'",
11
+ "cantParse%s": "'Can't parse '%s'",
12
+ "noConfigFileFound": "No config file found",
13
+ "pluginNameClash%s%s%s%s": "Plugin name clash: '%s (%s)' with '%s (%s)'",
14
+ "dependencyUnfulfilled%s%s": "Dependency for '%s' unfulfilled: %s",
15
+ "semverCheckFailed%s%s": "Semver check '%s' against '%s' failed",
16
+ "ddirNotExists%s": "Data directory '%s' doesn't exists!",
17
+ "signalReceived%s": "'%s' signal received",
18
+ "noAppletLoaded": "No applets loaded. Aborted!",
19
+ "oneOrMoreSharedTheSame%s%s": "One or more %s shared the same '%s'",
20
+ "bootCompleted%s": "Boot process completed in %s",
21
+ "runInEnv%s": "Run in '%s' environment",
22
+ "appRunningAsApplet": "App is running as applet...",
23
+ "setupBootOrder": "Setup boot order",
24
+ "configHandlers%s": "Config handlers: %s",
25
+ "exited": "Exited",
26
+ "appShutdown": "App shutdown",
27
+ "appletModeActivated": "Applet mode activated",
28
+ "collected%s%d": "%s collected: %d",
29
+ "attachMethods": "Attach methods",
30
+ "readConfigs": "Read configurations",
31
+ "checkAliasNameClash": "Checking alias & name clashes",
32
+ "checkDeps": "Checking dependencies",
33
+ "collectHooks": "Collect hooks",
34
+ "loadedPlugins%s": "Loaded plugins: %s",
35
+ "collecting%s": "Collecting %s",
36
+ "hookExecuted%s": "Hook '%s' executed",
37
+ "exitHandlers%s": "Exit handlers: %s",
38
+ "savedAs%s": "Saved as '%s'",
39
+ "aborted": "Aborted",
40
+ "done": "Done",
41
+ "error": "Error",
42
+ "language": "Language",
43
+ "langEnUs": "American English",
44
+ "langId": "Indonesian",
45
+ "gotoHome": "Goto Home",
46
+ "copyClipboard": "Copy to Clipboard",
47
+ "clear": "Clear",
48
+ "close": "Close",
49
+ "image": "Image",
50
+ "reset": "Reset",
51
+ "submit": "Submit",
52
+ "upload": "Upload",
53
+ "home": "Home",
54
+ "smallL": "small",
55
+ "mediumL": "medium",
56
+ "largeL": "large",
57
+ "sunday": "Sunday",
58
+ "monday": "Monday",
59
+ "tuesday": "Tuesday",
60
+ "wednesday": "Wednesday",
61
+ "thursday": "Thursday",
62
+ "friday": "Friday",
63
+ "saturday": "Saturday",
64
+ "sun": "Sun",
65
+ "mon": "Mon",
66
+ "tue": "Tue",
67
+ "wed": "Wed",
68
+ "thu": "Thu",
69
+ "fri": "Fri",
70
+ "sat": "Sat",
71
+ "back": "Back",
72
+ "forward": "Forward",
73
+ "weekends": "Weekends",
74
+ "workingDays": "Working Days",
75
+ "search": "Search",
76
+ "prev": "Prev",
77
+ "next": "Next",
78
+ "large": "Large",
79
+ "small": "Small",
80
+ "center": "Center",
81
+ "height": "Height",
82
+ "source": "Source",
83
+ "ok": "OK",
84
+ "cancel": "Cancel",
85
+ "information": "Information",
86
+ "warning": "Warning",
87
+ "danger": "Danger",
88
+ "apply": "Apply",
89
+ "options": "Options",
90
+ "confirmation": "Confirmation",
91
+ "statistics": "Statistics",
92
+ "general": "General",
93
+ "meta": "Meta",
94
+ "copied": "Copied",
95
+ "name": "Name",
96
+ "role": "Role",
97
+ "phone": "Phone",
98
+ "secondL": "second",
99
+ "minuteL": "minute",
100
+ "hourL": "hour",
101
+ "dayL": "day",
102
+ "monthL": "month",
103
+ "yearL": "year",
104
+ "second": "Second",
105
+ "minute": "Minute",
106
+ "hour": "Hour",
107
+ "day": "Day",
108
+ "month": "Month",
109
+ "year": "Year",
110
+ "description": "Description",
111
+ "dashboard": "Dashboard",
112
+ "task": "Task",
113
+ "allRightsReserved": "All rights reserved",
114
+ "date": "Date",
115
+ "status": "Status",
116
+ "missingPlugin%s": "Plugin '%s' is missing",
117
+ "unknownParser%s": "Unknown parser '%s'",
118
+ "unknownConn%s": "Unknown connection %s",
119
+ "connIs%s%s": "Connection '%s' is %s",
120
+ "connError%s%s": "Connection '%s' error: %s",
121
+ "closedL": "closed",
122
+ "openedL": "opened",
123
+ "connectedL": "connected",
124
+ "disconnectedL": "disconnected",
125
+ "endedL": "ended",
126
+ "offlineL": "offline",
127
+ "reconnectingL": "reconnecting",
128
+ "connMustHave%s": "Connection must have '%s'",
129
+ "notFound%s%s": "%s '%s' not found",
130
+ "connection": "Connection",
131
+ "file": "File",
132
+ "applet": "Applet",
133
+ "unsupported%s%s": "Unsupported %s '%s'",
134
+ "error%": "Error: %s",
135
+ "savedAs%%": "%s saved as '%s'"
136
+ }
@@ -0,0 +1,136 @@
1
+ {
2
+ "packageNotFoundOrNotBajo%s": "Package '%s' not found or isn't a valid Bajo package",
3
+ "unknownPluginOrNotLoaded%s": "Unknown plugin '%s' or plugin isn't loaded yet",
4
+ "collectionExists%s": "Collection '%s' already exists",
5
+ "cantLocateNpmGlobalDir": "Can't locate npm global module directory",
6
+ "cantLocateGlobalDir%s": "Can't locate '%s' global module directory",
7
+ "cantFindMethod%s": "Can't find method named '%s'",
8
+ "pluginWithALiasNotLoaded%s": "Plugin with alias '%s' is not loaded",
9
+ "cantFind%s": "Can't find %s",
10
+ "dtUnparsable%s": "Date/time unparsable '%s'",
11
+ "cantParse%s": "'Can't parse '%s'",
12
+ "noConfigFileFound": "No config file found",
13
+ "pluginNameClash%s%s%s%s": "Plugin name clash: '%s (%s)' with '%s (%s)'",
14
+ "dependencyUnfulfilled%s%s": "Dependency for '%s' unfulfilled: %s",
15
+ "semverCheckFailed%s%s": "Semver check '%s' against '%s' failed",
16
+ "ddirNotExists%s": "Data directory '%s' doesn't exists!",
17
+ "signalReceived%s": "'%s' signal received",
18
+ "noAppletLoaded": "No applets loaded. Aborted!",
19
+ "oneOrMoreSharedTheSame%s%s": "One or more %s shared the same '%s'",
20
+ "bootCompleted%s": "Boot process completed in %s",
21
+ "runInEnv%s": "Run in '%s' environment",
22
+ "appRunningAsApplet": "App is running as applet...",
23
+ "setupBootOrder": "Setup boot order",
24
+ "configHandlers%s": "Pengatur konfigurasi: %s",
25
+ "exited": "Exited",
26
+ "appShutdown": "App shutdown",
27
+ "appletModeActivated": "Applet mode activated",
28
+ "collected%s%d": "%s collected: %d",
29
+ "attachMethods": "Attach methods",
30
+ "readConfigs": "Read configurations",
31
+ "checkAliasNameClash": "Checking alias & name clashes",
32
+ "checkDeps": "Checking dependencies",
33
+ "collectHooks": "Collect hooks",
34
+ "loadedPlugins%s": "Loaded plugins: %s",
35
+ "collecting%s": "Collecting %s",
36
+ "hookExecuted%s": "Hook '%s' executed",
37
+ "exitHandlers%s": "Exit handlers: %s",
38
+ "savedAs%s": "Saved as '%s'",
39
+ "aborted": "Dibatalkan",
40
+ "done": "Selesai",
41
+ "error": "Kesalahan",
42
+ "language": "Bahasa",
43
+ "langEnUs": "Bahasa Inggris Amerika",
44
+ "langId": "Bahasa Indonesia",
45
+ "gotoHome": "Ke Beranda",
46
+ "copyClipboard": "Kopi ke Papan Tempel",
47
+ "clear": "Bersihkan",
48
+ "close": "Tutup",
49
+ "image": "Gambar",
50
+ "reset": "Reset",
51
+ "submit": "Kirim",
52
+ "upload": "Unggah",
53
+ "home": "Beranda",
54
+ "smallL": "kecil",
55
+ "mediumL": "menengah",
56
+ "largeL": "besar",
57
+ "sunday": "Minggu",
58
+ "monday": "Senin",
59
+ "tuesday": "Selasa",
60
+ "wednesday": "Rabu",
61
+ "thursday": "Kamis",
62
+ "friday": "Jumat",
63
+ "saturday": "Sabtu",
64
+ "sun": "Min",
65
+ "mon": "Sen",
66
+ "tue": "Sel",
67
+ "wed": "Rab",
68
+ "thu": "Kam",
69
+ "fri": "Jum",
70
+ "sat": "Sab",
71
+ "back": "Kembali",
72
+ "forward": "Maju",
73
+ "weekends": "Akhir Minggu",
74
+ "workingDays": "Hari Kerja",
75
+ "search": "Cari",
76
+ "prev": "Sebelumnya",
77
+ "next": "Berikutnya",
78
+ "large": "Besar",
79
+ "small": "Kecil",
80
+ "center": "Tengah",
81
+ "height": "Tinggi",
82
+ "source": "Sumber",
83
+ "ok": "Oke",
84
+ "cancel": "Batal",
85
+ "information": "Informasi",
86
+ "warning": "Perhatian",
87
+ "danger": "Bahaya",
88
+ "apply": "Terapkan",
89
+ "options": "Opsi-opsi",
90
+ "confirmation": "Konfirmasi",
91
+ "statistics": "Statistik",
92
+ "general": "Umum",
93
+ "meta": "Meta",
94
+ "copied": "Tertempel!",
95
+ "name": "Nama",
96
+ "role": "Peran",
97
+ "phone": "Telpon",
98
+ "secondL": "detik",
99
+ "minuteL": "menit",
100
+ "hourL": "jam",
101
+ "dayL": "hari",
102
+ "monthL": "bulan",
103
+ "yearL": "tahun",
104
+ "second": "Detik",
105
+ "minute": "Menit",
106
+ "hour": "Jam",
107
+ "day": "Hari",
108
+ "month": "Bulan",
109
+ "year": "Tahun",
110
+ "description": "Keterangan",
111
+ "dashboard": "Dasbor",
112
+ "task": "Pekerjaan",
113
+ "allRightsReserved": "Hak cipta dilindungi Undang-undang",
114
+ "date": "Tanggal",
115
+ "status": "Status",
116
+ "missingPlugin%s": "Plugin '%s' tidak ditemukan",
117
+ "unknownParser%s": "Parser tak dikenal '%s'",
118
+ "unknownConn%s": "Koneksi tak dikenal '%s'",
119
+ "connIs%s%s": "Koneksi '%s' %s",
120
+ "connError%s%s": "Koneksi '%s' ada kesalahan: %s",
121
+ "closedL": "tertutup",
122
+ "openedL": "terbuka",
123
+ "connectedL": "terhubung",
124
+ "disconnectedL": "terputus",
125
+ "endedL": "berhenti",
126
+ "offlineL": "offline",
127
+ "reconnectingL": "mencoba menghubung kembali",
128
+ "connMustHave%s": "Koneksi harus memiliki '%s'",
129
+ "notFound%s%s": "%s '%s' tidak ditemukan",
130
+ "connection": "Koneksi",
131
+ "file": "Berkas",
132
+ "applet": "Applet",
133
+ "unsupported%s%s": "%s '%s' tidak didukung",
134
+ "error%": "Kesalahan: %s",
135
+ "savedAs%%": "%s disimpan sbg '%s'"
136
+ }
package/boot/class/app.js CHANGED
@@ -31,7 +31,6 @@ class App {
31
31
  addPlugin (plugin) {
32
32
  if (this[plugin.name]) throw new Error(`Plugin '${plugin.name}' added already`)
33
33
  this[plugin.name] = plugin
34
- plugin.initPrint()
35
34
  }
36
35
 
37
36
  dump (...args) {
@@ -63,7 +62,7 @@ class App {
63
62
  // boot complete
64
63
  await bajo.runHook('bajo:bootComplete')
65
64
  const elapsed = new Date() - bajo.runAt
66
- bajo.log.info('Boot process completed in %s', bajo.secToHms(elapsed, true))
65
+ bajo.log.info('bootCompleted%s', bajo.secToHms(elapsed, true))
67
66
  if (bajo.applet) await runAsApplet.call(bajo)
68
67
  }
69
68
  }
@@ -26,6 +26,6 @@ export default async function () {
26
26
  this.lib.outmatch = outmatch
27
27
  // last cleanup
28
28
  if (!fs.existsSync(this.dir.data)) {
29
- this.log.warn('Data directory \'%s\' doesn\'t exists!', this.dir.data)
29
+ this.log.warn('ddirNotExists%s', this.dir.data)
30
30
  }
31
31
  }
@@ -5,7 +5,7 @@ import getModuleDir from '../method/get-module-dir.js'
5
5
  const { reduce, map, isNaN, trim, forOwn, orderBy } = lodash
6
6
 
7
7
  async function bootOrder () {
8
- this.log.debug('Setup boot order')
8
+ this.log.debug('setupBootOrder')
9
9
  const order = reduce(this.pluginPkgs, (o, k, i) => {
10
10
  const key = map(k.split(':'), m => trim(m))
11
11
  if (key[1] && !isNaN(Number(key[1]))) o[key[0]] = Number(key[1])
@@ -16,7 +16,7 @@ async function bootOrder () {
16
16
  for (let n of this.pluginPkgs) {
17
17
  n = map(n.split(':'), m => trim(m))[0]
18
18
  const dir = n === this.mainNs ? (`${this.dir.base}/${this.mainNs}`) : getModuleDir(n)
19
- if (n !== this.mainNs && !fs.existsSync(`${dir}/bajo`)) throw this.error('Package \'%s\' not found or isn\'t a valid Bajo package', n)
19
+ if (n !== this.mainNs && !fs.existsSync(`${dir}/bajo`)) throw this.error('packageNotFoundOrNotBajo%s', n)
20
20
  norder[n] = NaN
21
21
  try {
22
22
  norder[n] = Number(trim(await fs.readFile(`${dir}/bajo/.bootorder`, 'utf8')))
@@ -28,7 +28,7 @@ async function bootOrder () {
28
28
  result.push(item)
29
29
  })
30
30
  this.pluginPkgs = map(orderBy(result, ['v']), 'k')
31
- this.log.info('Run in \'%s\' environment', this.envs[this.config.env])
31
+ this.log.info('runInEnv%s', this.envs[this.config.env])
32
32
  // misc
33
33
  this.freeze(this.config)
34
34
  }
@@ -21,6 +21,19 @@ const defConfig = {
21
21
  traceHook: false
22
22
  },
23
23
  lang: Intl.DateTimeFormat().resolvedOptions().lang ?? 'en-US',
24
+ intl: {
25
+ supported: ['en-US', 'id'],
26
+ fallback: 'en-US',
27
+ lookupOrder: [],
28
+ format: {
29
+ emptyValue: '',
30
+ datetime: { dateStyle: 'medium', 'timeStyle': 'short' },
31
+ date: { dateStyle: 'medium' },
32
+ time: { timeStyle: 'short' },
33
+ float: { maximumFractionDigits: 2 },
34
+ integer: {}
35
+ }
36
+ },
24
37
  exitHandler: true
25
38
  }
26
39
 
@@ -57,6 +70,7 @@ export async function buildExtConfig () {
57
70
  this.config.exitHandler = false
58
71
  }
59
72
  const exts = map(this.configHandlers, 'ext')
60
- this.log.init()
61
- this.log.debug('Config handlers: %s', join(exts))
73
+ this.initPrint()
74
+ this.initLog()
75
+ this.log.debug('configHandlers%s', join(exts))
62
76
  }
@@ -1,15 +1,15 @@
1
1
  async function exit (signal) {
2
2
  const { eachPlugins } = this
3
- this.log.warn('\'%s\' signal received', signal)
3
+ this.log.warn('signalReceived%s', signal)
4
4
  await eachPlugins(async function ({ ns }) {
5
5
  const handler = this.exitHandler
6
6
  if (!handler) return undefined
7
7
  try {
8
8
  await handler.call(this)
9
9
  } catch (err) {}
10
- this.log.debug('Exited')
10
+ this.log.debug('exited')
11
11
  })
12
- this.log.debug('App shutdown')
12
+ this.log.debug('appShutdown')
13
13
  process.exit(0)
14
14
  }
15
15
 
@@ -4,9 +4,9 @@ async function runAsApplet () {
4
4
  this.app.bajo.applets.push({ ns, file, alias })
5
5
  }, { glob: 'applet.js', prefix: 'bajoCli' })
6
6
 
7
- this.log.debug('Applet mode activated')
8
- this.print.info('App is running as applet...')
9
- if (this.applets.length === 0) this.print.fatal('No applets loaded. Aborted!')
7
+ this.log.debug('appletModeActivated')
8
+ this.print.info('appRunningAsApplet')
9
+ if (this.applets.length === 0) this.print.fatal('noAppletLoaded')
10
10
  let name = this.applet
11
11
  if (!isString(this.applet)) {
12
12
  const select = await this.importPkg('bajoCli:@inquirer/select')
@@ -17,7 +17,7 @@ async function runAsApplet () {
17
17
  }
18
18
  const [ns, path] = name.split(':')
19
19
  const applet = find(this.applets, a => (a.ns === ns || a.alias === ns))
20
- if (!applet) this.print.fatal('Applet \'%s\' not found. Aborted!', name)
20
+ if (!applet) this.print.fatal('notFound%s%s', this.print.write('applet'), name)
21
21
  await this.runHook(`${this.app[applet.ns]}:beforeAppletRun`)
22
22
  await this.app.bajoCli.runApplet(applet, path, ...this.app.args)
23
23
  await this.runHook(`${this.app[applet.ns]}:afterAppletRun`)
@@ -19,7 +19,7 @@ function breakNsPath (item = '', defaultNs = 'bajo', checkNs = true) {
19
19
  const plugin = this.getPlugin(ns)
20
20
  if (plugin) ns = plugin.name
21
21
  }
22
- if (!this.app[ns]) throw this.error('Unknown plugin \'%s\' or plugin isn\'t loaded yet')
22
+ if (!this.app[ns]) throw this.error('unknownPluginOrNotLoaded%s')
23
23
  }
24
24
  const fullPath = path
25
25
  let qs
@@ -10,14 +10,14 @@ async function buildCollections (options = {}) {
10
10
  const cfg = this.app[ns].getConfig()
11
11
  let items = get(cfg, container, [])
12
12
  if (!isArray(items)) items = [items]
13
- this.app[ns].log.trace('Collecting %s', this.app[ns].print.write(container))
13
+ this.app[ns].log.trace('collecting%s', this.app[ns].print.write(container))
14
14
  await runHook(`${ns}:${camelCase('beforeBuildCollection')}`, container)
15
15
  const deleted = []
16
16
  for (const index in items) {
17
17
  const item = items[index]
18
18
  if (useDefaultName) {
19
19
  if (!has(item, 'name')) {
20
- if (find(items, { name: 'default' })) throw this.app[ns].error('Collection \'default\' already exists')
20
+ if (find(items, { name: 'default' })) throw this.app[ns].error('collectionExists%s', 'default')
21
21
  else item.name = 'default'
22
22
  }
23
23
  }
@@ -36,12 +36,12 @@ async function buildCollections (options = {}) {
36
36
  else {
37
37
  const checker = set({}, d, c[d])
38
38
  const match = filter(items, checker)
39
- if (match.length > 1) this.app[ns].fatal('One or more %s shared the same \'%s\'', container, join(dupChecks.filter(i => !isFunction(i))))
39
+ if (match.length > 1) this.app[ns].fatal('oneOrMoreSharedTheSame%s%s', container, join(dupChecks.filter(i => !isFunction(i))))
40
40
  }
41
41
  }
42
42
  }
43
43
  await runHook(`${ns}:${camelCase('afterBuildCollection')}`, container)
44
- this.app[ns].log.debug('%s collected: %d', this.app[ns].print.write(container), items.length)
44
+ this.app[ns].log.debug('collected%s%d', this.app[ns].print.write(container), items.length)
45
45
  return items
46
46
  }
47
47
 
@@ -0,0 +1,36 @@
1
+ function format (value, type, lang, options = {}) {
2
+ const { defaultsDeep } = this.app.bajo
3
+ const { format } = this.config.intl
4
+ const { emptyValue = format.emptyValue } = options
5
+ if ([undefined, null, ''].includes(value)) return emptyValue
6
+ if (type === 'auto') {
7
+ if (value instanceof Date) type = 'datetime'
8
+ }
9
+ if (['integer', 'smallint'].includes(type)) {
10
+ value = parseInt(value)
11
+ if (isNaN(value)) return emptyValue
12
+ const setting = defaultsDeep(options.integer, format.integer)
13
+ return new Intl.NumberFormat(lang, setting).format(value)
14
+ }
15
+ if (['float', 'double'].includes(type)) {
16
+ value = parseFloat(value)
17
+ if (isNaN(value)) return emptyValue
18
+ if (this.app.bajoSpatial && options.latitude) return this.app.bajoSpatial.latToDms(value)
19
+ if (this.app.bajoSpatial && options.longitude) return this.app.bajoSpatial.lngToDms(value)
20
+ const setting = defaultsDeep(options.float, format.float)
21
+ return new Intl.NumberFormat(lang, setting).format(value)
22
+ }
23
+ if (['datetime', 'date'].includes(type)) {
24
+ const setting = defaultsDeep(options[type], format[type])
25
+ return new Intl.DateTimeFormat(lang, setting).format(new Date(value))
26
+ }
27
+ if (['time'].includes(type)) {
28
+ const setting = defaultsDeep(options.time, format.time)
29
+ return new Intl.DateTimeFormat(lang, setting).format(new Date(`1970-01-01T${value}Z`))
30
+ }
31
+ if (['array'].includes(type)) return value.join(', ')
32
+ if (['object'].includes(type)) return JSON.stringify(value)
33
+ return value
34
+ }
35
+
36
+ export default format
@@ -11,7 +11,7 @@ function getGlobalModuleDir (pkgName, silent = true) {
11
11
  const npmPath = getGlobalPath('npm')
12
12
  if (!npmPath) {
13
13
  if (silent) return
14
- throw this.error('Can\'t locate npm global module directory', { code: 'BAJO_CANT_LOCATE_NPM_GLOBAL_DIR' })
14
+ throw this.error('cantLocateNpmGlobalDir', { code: 'BAJO_CANT_LOCATE_NPM_GLOBAL_DIR' })
15
15
  }
16
16
  nodeModulesDir = dropRight(resolvePath(npmPath).split('/'), 1).join('/')
17
17
  process.env.BAJO_GLOBAL_MODULE_DIR = nodeModulesDir
@@ -20,7 +20,7 @@ function getGlobalModuleDir (pkgName, silent = true) {
20
20
  const dir = `${nodeModulesDir}/${pkgName}`
21
21
  if (!fs.existsSync(dir)) {
22
22
  if (silent) return
23
- throw this.error('Can\'t locate \'%s\' global module directory', pkgName, { code: 'BAJO_CANT_LOCATE_MODULE_GLOBAL_DIR' })
23
+ throw this.error('cantLocateGlobalDir%s', pkgName, { code: 'BAJO_CANT_LOCATE_MODULE_GLOBAL_DIR' })
24
24
  }
25
25
  return dir
26
26
  }
@@ -6,7 +6,7 @@ function getMethod (name = '', thrown = true) {
6
6
  const { ns, path } = this.breakNsPath(name)
7
7
  const method = get(this.app, `${ns}.${path}`)
8
8
  if (method && isFunction(method)) return method
9
- if (thrown) throw this.error('Can\'t find method named \'%s\'', name)
9
+ if (thrown) throw this.error('cantFindMethod%s', name)
10
10
  }
11
11
 
12
12
  export default getMethod
@@ -13,7 +13,7 @@ function getPlugin (name, silent) {
13
13
  }
14
14
  if (!plugin) {
15
15
  if (silent) return false
16
- throw this.error('Plugin with alias \'%s\' is not loaded', name)
16
+ throw this.error('pluginWithALiasNotLoaded%s', name)
17
17
  }
18
18
  name = plugin.name
19
19
  }
@@ -39,7 +39,7 @@ async function importPkg (...pkgs) {
39
39
  }
40
40
  result[name] = mod
41
41
  }
42
- if (notFound.length > 0) throw this.error('Can\'t find %s', this.join(notFound))
42
+ if (notFound.length > 0) throw this.error('cantFind%s', this.join(notFound))
43
43
  if (pkgs.length === 1) return result[keys(result)[0]]
44
44
  if (opts.asObject) return result
45
45
  return values(result)
@@ -3,7 +3,7 @@ import dotenvParseVariables from 'dotenv-parse-variables'
3
3
  import ms from 'ms'
4
4
  import dayjs from '../../../lib/dayjs.js'
5
5
  import isSet from './is-set.js'
6
- import translate from '../../../lib/translate.js'
6
+ // import translate from '../../../lib/translate.js'
7
7
 
8
8
  const { isPlainObject, isArray, isNumber, set, cloneDeep, isString, omit } = lodash
9
9
  const statics = ['*']
@@ -14,11 +14,11 @@ function parseDur (val) {
14
14
 
15
15
  function parseDt (val) {
16
16
  const dt = dayjs(val)
17
- if (!dt.isValid()) throw this.error('Unparsed date/time \'%s\'', val)
17
+ if (!dt.isValid()) throw this.error('dtUnparsable%s', val)
18
18
  return dt.toDate()
19
19
  }
20
20
 
21
- function parseObject (input, { silent = true, parseValue = false, i18n, ns } = {}) {
21
+ function parseObject (input, { silent = true, parseValue = false, lang, ns } = {}) {
22
22
  let obj = cloneDeep(input)
23
23
  const keys = Object.keys(obj)
24
24
  const me = this
@@ -38,14 +38,16 @@ function parseObject (input, { silent = true, parseValue = false, i18n, ns } = {
38
38
  if (statics.includes(v)) obj[k] = v
39
39
  else if (k.startsWith('t:') && isString(v)) {
40
40
  const newK = k.slice(2)
41
- if (i18n) {
41
+ if (lang) {
42
42
  const scope = ns ? me.app[ns] : me
43
43
  let [text, ...args] = v.split('|')
44
44
  args = args.map(a => {
45
- if (a.slice(0, 2) === 't:') a = translate.call(scope, i18n, a.slice(2))
45
+ // if (a.slice(0, 2) === 't:') a = translate.call(scope, i18n, a.slice(2))
46
+ if (a.slice(0, 2) === 't:') a = scope.print.write(lang, a.slice(2))
46
47
  return a
47
48
  })
48
- obj[newK] = translate.call(scope, i18n, text, ...args)
49
+ // obj[newK] = translate.call(scope, i18n, text, ...args)
50
+ obj[newK] = scope.print.write(text, lang, ...args)
49
51
  } else obj[newK] = v
50
52
  mutated.push(k)
51
53
  } else if (parseValue) {
@@ -22,7 +22,7 @@ async function readConfig (file, { ns, pattern, globOptions = {}, ignoreError, d
22
22
  if (!['', '.*'].includes(ext)) {
23
23
  const item = find(this.app.bajo.configHandlers, { ext })
24
24
  if (!item) {
25
- if (!ignoreError) throw this.error('Can\'t parse \'%s\'', file, { code: 'BAJO_CONFIG_NO_PARSER' })
25
+ if (!ignoreError) throw this.error('cantParse%s', file, { code: 'BAJO_CONFIG_NO_PARSER' })
26
26
  return parseObject(defValue)
27
27
  }
28
28
  return parseObject(await item.readHandler.call(this.app[ns], file, opts))
@@ -30,7 +30,7 @@ async function readConfig (file, { ns, pattern, globOptions = {}, ignoreError, d
30
30
  const item = pattern ?? `${fname}.{${map(map(this.app.bajo.configHandlers, 'ext'), k => k.slice(1)).join(',')}}`
31
31
  const files = await fg(item, globOptions)
32
32
  if (files.length === 0) {
33
- if (!ignoreError) throw this.error('No config file found', { code: 'BAJO_CONFIG_FILE_NOT_FOUND' })
33
+ if (!ignoreError) throw this.error('noConfigFileFound', { code: 'BAJO_CONFIG_FILE_NOT_FOUND' })
34
34
  return parseObject(defValue)
35
35
  }
36
36
  let config = defValue
@@ -38,7 +38,7 @@ async function readConfig (file, { ns, pattern, globOptions = {}, ignoreError, d
38
38
  const ext = path.extname(f).toLowerCase()
39
39
  const item = find(this.app.bajo.configHandlers, { ext })
40
40
  if (!item) {
41
- if (!ignoreError) throw this.error('Can\'t parse \'%s\'', f, { code: 'BAJO_CONFIG_NO_PARSER' })
41
+ if (!ignoreError) throw this.error('cantParse%s', f, { code: 'BAJO_CONFIG_NO_PARSER' })
42
42
  continue
43
43
  }
44
44
  config = await item.readHandler.call(this.app[ns], f, opts)
@@ -5,7 +5,7 @@ import parseObject from './parse-object.js'
5
5
  const { isEmpty } = lodash
6
6
 
7
7
  function readJson (file, thrownNotFound) {
8
- if (!fs.existsSync(file) && thrownNotFound) throw this.error('File \'%s\' not found', file)
8
+ if (!fs.existsSync(file) && thrownNotFound) throw this.error('notFound%s%s', this.print.write('file'), file)
9
9
  let resp = fs.readFileSync(file, 'utf8')
10
10
  if (isEmpty(resp)) resp = '{}'
11
11
  return parseObject(JSON.parse(resp))
@@ -18,7 +18,7 @@ async function runHook (hookName, ...args) {
18
18
  resp: res
19
19
  })
20
20
  if (path.startsWith('once')) removed.push(i)
21
- if (this.config.log.traceHook) scope.log.trace('Hook \'%s\' executed', hookName)
21
+ if (this.config.log.traceHook) scope.log.trace('hookExecuted%s', hookName)
22
22
  }
23
23
  if (removed.length > 0) pullAt(this.app.bajo.hooks, removed)
24
24
 
@@ -12,7 +12,7 @@ async function saveAsDownload (file, obj, printSaved = true) {
12
12
  const dir = path.dirname(fname)
13
13
  if (!fs.existsSync(dir)) fs.ensureDirSync(dir)
14
14
  await fs.writeFile(fname, obj, 'utf8')
15
- if (printSaved) print.succeed('Saved as \'%s\'', path.resolve(fname), { skipSilence: true })
15
+ if (printSaved) print.succeed('savedAs%s', path.resolve(fname), { skipSilence: true })
16
16
  return fname
17
17
  }
18
18
 
@@ -3,7 +3,7 @@ import createMethod from '../../../lib/create-method.js'
3
3
  async function attachMethod () {
4
4
  const { eachPlugins } = this.bajo
5
5
  const me = this
6
- me.bajo.log.debug('Attach methods')
6
+ me.bajo.log.debug('attachMethods')
7
7
  await eachPlugins(async function ({ ns, pkgName }) {
8
8
  const dir = ns === me.bajo.mainNs ? (`${me.bajo.dir.base}/${me.bajo.mainNs}`) : me.bajo.getModuleDir(pkgName)
9
9
  const num = await createMethod.call(me[ns], `${dir}/bajo/method`, pkgName)
@@ -3,9 +3,12 @@ import lodash from 'lodash'
3
3
  const { camelCase } = lodash
4
4
 
5
5
  async function buildConfig () {
6
- this.bajo.log.debug('Read configurations')
6
+ this.bajo.log.debug('readConfigs')
7
7
  for (const pkg of this.bajo.pluginPkgs) {
8
- await this[camelCase(pkg)].loadConfig()
8
+ const plugin = this[camelCase(pkg)]
9
+ await plugin.loadConfig()
10
+ plugin.initPrint()
11
+ plugin.initLog()
9
12
  }
10
13
  }
11
14
 
@@ -4,13 +4,13 @@ const { find } = lodash
4
4
 
5
5
  async function checkAlias () {
6
6
  const { eachPlugins } = this.bajo
7
- this.bajo.log.debug('Checking alias & name clashes')
7
+ this.bajo.log.debug('checkAliasNameClash')
8
8
  const refs = []
9
9
  await eachPlugins(async function ({ ns, pkgName, alias }) {
10
10
  let item = find(refs, { ns })
11
- if (item) throw this.error('Plugin name clash: \'%s (%s)\' with \'%s (%s)\'', ns, pkgName, item.ns, item.pkgName, { code: 'BAJO_NAME_CLASH' })
11
+ if (item) throw this.error('pluginNameClash%s%s%s%s', ns, pkgName, item.ns, item.pkgName, { code: 'BAJO_NAME_CLASH' })
12
12
  item = find(refs, { alias })
13
- if (item) throw this.error('Plugin alias clash: \'%s (%s)\' with \'%s (%s)\'', alias, pkgName, item.alias, item.pkgName, { code: 'BAJO_ALIAS_CLASH' })
13
+ if (item) throw this.error('pluginNameClash%s%s%s%s', alias, pkgName, item.alias, item.pkgName, { code: 'BAJO_ALIAS_CLASH' })
14
14
  refs.push({ ns, alias, pkgName })
15
15
  })
16
16
  }
@@ -15,14 +15,14 @@ async function runner ({ ns, pkgName }) {
15
15
  const deps = keys(odep)
16
16
  if (deps.length > 0) {
17
17
  if (intersection(this.app.bajo.pluginPkgs, deps).length !== deps.length) {
18
- throw this.error('Dependency for \'%s\' unfulfilled: %s', pkgName, join(deps), { code: 'BAJO_DEPENDENCY' })
18
+ throw this.error('dependencyUnfulfilled%s%s', pkgName, join(deps), { code: 'BAJO_DEPENDENCY' })
19
19
  }
20
20
  each(deps, d => {
21
21
  if (!odep[d]) return
22
22
  const ver = get(this.app[camelCase(d)], 'config.pkg.version')
23
23
  if (!ver) return
24
24
  if (!semver.satisfies(ver, odep[d])) {
25
- throw this.error('Semver check \'%s\' against \'%s\' failed', pkgName, `${d}@${odep[d]}`, { code: 'BAJO_DEPENDENCY_SEMVER' })
25
+ throw this.error('semverCheckFailed%s%s', pkgName, `${d}@${odep[d]}`, { code: 'BAJO_DEPENDENCY_SEMVER' })
26
26
  }
27
27
  })
28
28
  }
@@ -30,7 +30,7 @@ async function runner ({ ns, pkgName }) {
30
30
 
31
31
  async function checkDependency () {
32
32
  const { eachPlugins } = this.bajo
33
- this.bajo.log.debug('Checking dependencies')
33
+ this.bajo.log.debug('checkDeps')
34
34
  await eachPlugins(async function ({ ns, pkgName, config }) {
35
35
  await runner.call(this, { ns, pkgName, config })
36
36
  })
@@ -8,7 +8,7 @@ async function collectExitHandlers () {
8
8
  this.app[ns].exitHandler = mod
9
9
  nss.push(ns)
10
10
  })
11
- this.bajo.log.trace('Exit handlers: %s', nss.length === 0 ? print.write('none') : join(nss))
11
+ this.bajo.log.trace('exitHandlers%s', nss.length === 0 ? print.write('none') : join(nss))
12
12
  }
13
13
 
14
14
  export default collectExitHandlers
@@ -6,7 +6,7 @@ async function collectHooks () {
6
6
  const { eachPlugins, runHook, isLogInRange, importModule, breakNsPathFromFile } = this.bajo
7
7
  const me = this
8
8
  me.bajo.hooks = this.bajo.hooks ?? []
9
- me.bajo.log.debug('Collect hooks')
9
+ me.bajo.log.debug('collectHooks')
10
10
  // collects
11
11
  await eachPlugins(async function ({ ns, dir, file }) {
12
12
  const { fullNs, path } = breakNsPathFromFile({ file, dir, baseNs: ns, suffix: '/hook/' })
@@ -15,7 +15,7 @@ async function run () {
15
15
  })
16
16
  await runHook(`bajo:${camelCase(`after ${method} all plugins`)}`)
17
17
  }
18
- me.bajo.log.debug('Loaded plugins: %s', join(map(me.bajo.pluginPkgs, b => camelCase(b))))
18
+ me.bajo.log.debug('loadedPlugins%s', join(map(me.bajo.pluginPkgs, b => camelCase(b))))
19
19
  }
20
20
 
21
21
  export default run
package/boot/class/log.js CHANGED
@@ -2,7 +2,6 @@ import os from 'os'
2
2
  import lodash from 'lodash'
3
3
  import levels from './bajo-core/method/log-levels.js'
4
4
  import isLogInRange from './bajo-core/method/is-log-in-range.js'
5
- import translate from '../lib/translate.js'
6
5
  import dayjs from 'dayjs'
7
6
 
8
7
  const { isEmpty, without, merge, upperFirst } = lodash
@@ -18,7 +17,8 @@ class Log {
18
17
  }
19
18
 
20
19
  write (text, ...args) {
21
- return translate.call(this.plugin, null, text, ...args)
20
+ const lang = this.plugin.app.bajo.config.lang
21
+ return this.plugin.print.write(text, lang, ...args)
22
22
  }
23
23
 
24
24
  isExtLogger () {
@@ -40,7 +40,7 @@ class Log {
40
40
  data = null
41
41
  }
42
42
  args = without(args, undefined)
43
- msg = this.write(`[%s] ${msg}`, this.plugin.name, ...args)
43
+ msg = `[${this.plugin.name}] ${this.write(msg, ...args)}`
44
44
  if (this.plugin.app[this.bajoLog] && this.plugin.app[this.bajoLog].logger) {
45
45
  this.plugin.app[this.bajoLog].logger[level](data, msg, ...args)
46
46
  } else {
@@ -14,7 +14,6 @@ class Plugin {
14
14
  this.config = {}
15
15
  this.lib = {}
16
16
  this.exitHandler = undefined
17
- this.initLog()
18
17
  }
19
18
 
20
19
  getConfig (path, options = {}) {
@@ -27,10 +26,12 @@ class Plugin {
27
26
 
28
27
  initLog () {
29
28
  this.log = new Log(this)
29
+ this.log.init()
30
30
  }
31
31
 
32
32
  initPrint (opts) {
33
33
  this.print = new Print(this, opts)
34
+ this.print.init()
34
35
  }
35
36
 
36
37
  error (msg, ...args) {
@@ -1,9 +1,11 @@
1
1
  import ora from 'ora'
2
2
  import lodash from 'lodash'
3
3
  import defaultsDeep from './bajo-core/method/defaults-deep.js'
4
- import translate from '../lib/translate.js'
4
+ import fs from 'fs-extra'
5
+ import Sprintf from 'sprintf-js'
6
+ const { sprintf } = Sprintf
5
7
 
6
- const { isPlainObject } = lodash
8
+ const { isPlainObject, get, without, reverse } = lodash
7
9
 
8
10
  class Print {
9
11
  constructor (plugin, opts = {}) {
@@ -12,6 +14,42 @@ class Print {
12
14
  this.startTime = this.plugin.app.bajo.lib.dayjs()
13
15
  this.setOpts()
14
16
  this.ora = ora(this.opts)
17
+ this.intl = {}
18
+ }
19
+
20
+ init () {
21
+ for (const l of this.plugin.app.bajo.config.intl.supported) {
22
+ this.intl[l] = {}
23
+ const path = `${this.plugin.dir.pkg}/bajo/intl/${l}.json`
24
+ if (!fs.existsSync(path)) continue
25
+ const trans = fs.readFileSync(path, 'utf8')
26
+ try {
27
+ this.intl[l] = JSON.parse(trans)
28
+ } catch (err) {}
29
+ }
30
+ }
31
+
32
+ write (text, lang, ...args) {
33
+ const fallback = this.plugin.app.bajo.config.intl.fallback
34
+ const plugins = reverse(without([...this.plugin.app.bajo.pluginNames], this.plugin.name))
35
+ plugins.unshift(this.plugin.name)
36
+ plugins.push('bajo')
37
+
38
+ let trans
39
+ for (const p of plugins) {
40
+ const root = get(this, `plugin.app.${p}.print.intl.${lang}`, {})
41
+ trans = get(root, text)
42
+ if (trans) break
43
+ }
44
+ if (!trans) {
45
+ for (const p of plugins) {
46
+ const root = get(this, `plugin.app.${p}.print.intl.${fallback}`, {})
47
+ trans = get(root, text)
48
+ if (trans) break
49
+ }
50
+ }
51
+ if (!trans) trans = text
52
+ return sprintf(trans, ...args)
15
53
  }
16
54
 
17
55
  setOpts (args = []) {
@@ -35,10 +73,6 @@ class Print {
35
73
  return this
36
74
  }
37
75
 
38
- write (text, ...args) {
39
- return translate.call(this.plugin, null, text, ...args)
40
- }
41
-
42
76
  getElapsed (unit = 'hms') {
43
77
  const u = unit === 'hms' ? 'second' : unit
44
78
  const elapsed = this.plugin.app.bajo.lib.dayjs().diff(this.startTime, u)
@@ -6,13 +6,13 @@ async function readAllConfigs (base) {
6
6
  let ext = {}
7
7
  // default config file
8
8
  try {
9
- cfg = await readConfig.call(this.bajo, `${base}.*`)
9
+ cfg = await readConfig.call(this.bajo, `${base}.*`, { ignoreError: true })
10
10
  } catch (err) {
11
11
  if (['BAJO_CONFIG_NO_PARSER'].includes(err.code)) throw err
12
12
  }
13
13
  // env based config file
14
14
  try {
15
- ext = await readConfig.call(this.bajo, `${base}-${this.bajo.config.env}.*`)
15
+ ext = await readConfig.call(this.bajo, `${base}-${this.bajo.config.env}.*`, { ignoreError: true })
16
16
  } catch (err) {
17
17
  if (!['BAJO_CONFIG_FILE_NOT_FOUND'].includes(err.code)) throw err
18
18
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bajo",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "A framework to build a giant monstrous app rapidly",
5
5
  "main": "boot/index.js",
6
6
  "scripts": {
@@ -1,31 +0,0 @@
1
- {
2
- "[%s] '%s' signal received": "[%s] Diterima signal '%s'",
3
- "[%s] Exited: %s": "[%s] Keluar: %s",
4
- "[%s] Program shutdown": "[%s] Program berakhir",
5
- "[%s] Exit handlings": "[%s] Pengaturan keluar",
6
- "[%s] Boot process completed in %s": "[%s] Proses boot komplit dalam waktu %s",
7
- "[%s] Run tool": "[%s] Jalankan perkakas",
8
- "[%s] Loaded plugins: %s": "[%s] Plugin termuat: %s",
9
- "[%s] Unloaded 'single' plugins: %s": "[%s] 'Single' plugin tak termuat: %s",
10
- "[%s] No %s found": "[%s] Tidak ditemukan %s",
11
- "[%s] Init plugin...": "[%s] Init plugin...",
12
- "[%s] Start plugin...": "[%s] Jalankan plugin...",
13
- "[%s] Collecting %s": "[%s] Mengumpulkan %s",
14
- "[%s] %s collected: %d": "[%s] Total %s terkumpul: %d",
15
- "- All -": "- Semua -",
16
- "Tool mode activated": "Mode perkakas diaktifkan",
17
- "App is running in tool mode...": "Aplikasi berjalan dalam mode perkakas",
18
- "No tool loaded. Aborted!": "Tidak ada perkakas yang termuat. Batalkan!",
19
- "Please select:": "Silahkan pilih:",
20
- "Tool '%s' not found. Aborted!": "perkakas '%s' tidak ditemukan. Batalkan!",
21
- "Please select a method:": "Silahkan pilih metode:",
22
- "Unknown method '%s'": "Metode '%s' tidak dikenal",
23
- "and": "dan",
24
- "or": "atau",
25
- "Yes": "Ya",
26
- "No": "Tidak",
27
- "[%s] Exited": "[%s] Telah keluar",
28
- "[%s] App shutdown": "[%s] Aplikasi dimatikan",
29
- "[%s] Collect %s": "",
30
- "[%s] %s support is disabled": ""
31
- }