bajo 0.2.14 → 0.2.16

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.
@@ -2,14 +2,9 @@ import buildHelper from './lib/build-helper.js'
2
2
  import logger from './lib/logger.js'
3
3
  import print from './lib/print.js'
4
4
  import fs from 'fs-extra'
5
- import dayjs from 'dayjs'
6
- import utc from 'dayjs/plugin/utc.js'
7
- import customParseFormat from 'dayjs/plugin/customParseFormat.js'
8
5
  import deepFreeze from 'deep-freeze-strict'
9
6
  import currentLoc from './helper/current-loc.js'
10
-
11
- dayjs.extend(utc)
12
- dayjs.extend(customParseFormat)
7
+ import dayjs from './lib/dayjs.js'
13
8
 
14
9
  export default async function () {
15
10
  this.bajo.helper = await buildHelper.call(this, `${currentLoc(import.meta).dir}/helper`)
@@ -17,9 +12,9 @@ export default async function () {
17
12
  if (shallow) Object.freeze(o)
18
13
  else deepFreeze(o)
19
14
  }
15
+ this.bajo.helper.dayjs = dayjs
20
16
  this.bajo.helper.print = print.call(this)
21
17
  this.bajo.helper.log = logger.call(this)
22
- this.bajo.helper.dayjs = dayjs
23
18
  this.bajo.helper.setImmediate = function () {
24
19
  return new Promise((resolve) => {
25
20
  setImmediate(() => resolve())
@@ -0,0 +1,38 @@
1
+ import { isPlainObject, isArray, isNumber } from 'lodash-es'
2
+ import ms from 'ms'
3
+ import dayjs from '../lib/dayjs.js'
4
+ import isSet from './is-set.js'
5
+
6
+ function parseDur (val) {
7
+ return isNumber(val) ? val : ms(val)
8
+ }
9
+
10
+ function parseDt (val) {
11
+ const dt = dayjs(val)
12
+ if (!dt.isValid()) throw Error(`Unparsed date/time '${val}'`)
13
+ return dt.toDate()
14
+ }
15
+
16
+ function parseObject (obj, silent = true) {
17
+ const keys = Object.keys(obj)
18
+ keys.forEach(k => {
19
+ const v = obj[k]
20
+ if (isPlainObject(v)) obj[k] = parseObject(v)
21
+ else if (isArray(v)) {
22
+ v.forEach((i, idx) => {
23
+ if (isPlainObject(i)) obj[k][idx] = parseObject(i)
24
+ })
25
+ } else if (isSet(v)) {
26
+ try {
27
+ if (k.slice(-3) === 'Dur') obj[k] = parseDur(v)
28
+ if (k.slice(-2) === 'Dt') obj[k] = parseDt(v)
29
+ } catch (err) {
30
+ obj[k] = undefined
31
+ if (!silent) throw err
32
+ }
33
+ }
34
+ })
35
+ return obj
36
+ }
37
+
38
+ export default parseObject
@@ -1,6 +1,7 @@
1
1
  import path from 'path'
2
2
  import resolvePath from './resolve-path.js'
3
3
  import readJson from './read-json.js'
4
+ import parseObject from './parse-object.js'
4
5
  import { find, map, isEmpty } from 'lodash-es'
5
6
  import error from './error.js'
6
7
  import fg from 'fast-glob'
@@ -12,22 +13,22 @@ async function readConfig (file, { pattern, globOptions = {}, ignoreError, defVa
12
13
  ext = ext.toLowerCase()
13
14
  if (['.mjs', '.js'].includes(ext)) {
14
15
  const { handler } = find(this.bajo.configHandlers, { ext })
15
- return await handler.call(this, file)
16
+ return parseObject(await handler.call(this, file))
16
17
  }
17
18
  if (ext === '.json') return await readJson(file)
18
19
  if (!['', '.*'].includes(ext)) {
19
20
  const item = find(this.bajo.configHandlers, { ext })
20
21
  if (!item) {
21
22
  if (!ignoreError) throw error.call(this, 'Can\'t parse \'%s\'', file, { code: 'BAJO_CONFIG_NO_PARSER' })
22
- return defValue
23
+ return parseObject(defValue)
23
24
  }
24
- return item.handler.call(this, file)
25
+ return parseObject(item.handler.call(this, file))
25
26
  }
26
27
  const item = pattern ?? `${fname}.{${map(map(this.bajo.configHandlers, 'ext'), k => k.slice(1)).join(',')}}`
27
28
  const files = await fg(item, globOptions)
28
29
  if (files.length === 0) {
29
30
  if (!ignoreError) throw error.call(this, 'No config file found', { code: 'BAJO_CONFIG_FILE_NOT_FOUND' })
30
- return defValue
31
+ return parseObject(defValue)
31
32
  }
32
33
  let config = defValue
33
34
  for (const f of files) {
@@ -40,7 +41,7 @@ async function readConfig (file, { pattern, globOptions = {}, ignoreError, defVa
40
41
  config = await item.handler.call(this, f)
41
42
  if (!isEmpty(config)) break
42
43
  }
43
- return config
44
+ return parseObject(config)
44
45
  }
45
46
 
46
47
  export default readConfig
@@ -1,11 +1,12 @@
1
1
  import fs from 'fs-extra'
2
2
  import { isEmpty } from 'lodash-es'
3
+ import parseObject from './parse-object.js'
3
4
 
4
5
  const readJson = (file, thrownNotFound) => {
5
6
  if (!fs.existsSync(file) && thrownNotFound) throw new Error('File \'%s\' not found', file)
6
7
  let resp = fs.readFileSync(file, 'utf8')
7
8
  if (isEmpty(resp)) resp = '{}'
8
- return JSON.parse(resp)
9
+ return parseObject(JSON.parse(resp))
9
10
  }
10
11
 
11
12
  export default readJson
@@ -10,7 +10,7 @@ async function saveAsDownload (file, obj, printSaved = true) {
10
10
  const dir = path.dirname(fname)
11
11
  if (!fs.existsSync(dir)) fs.ensureDirSync(dir)
12
12
  await fs.writeFile(fname, obj, 'utf8')
13
- if (printSaved) print.bora('Saved as \'%s\'', path.resolve(fname), { skipSilence: true }).succeed()
13
+ if (printSaved) print.succeed('Saved as \'%s\'', path.resolve(fname), { skipSilence: true })
14
14
  return fname
15
15
  }
16
16
 
@@ -1,15 +1,24 @@
1
- // taken from: https://stackoverflow.com/questions/1322732/convert-seconds-to-hh-mm-ss-with-javascript
1
+ import { padStart } from 'lodash-es'
2
2
 
3
- function secToHms (secs) {
3
+ // based on: https://stackoverflow.com/questions/1322732/convert-seconds-to-hh-mm-ss-with-javascript
4
+
5
+ function secToHms (secs, ms) {
6
+ let remain
7
+ if (ms) {
8
+ remain = secs % 1000
9
+ secs = Math.floor(secs / 1000)
10
+ }
4
11
  const secNum = parseInt(secs, 10)
5
12
  const hours = Math.floor(secNum / 3600)
6
13
  const minutes = Math.floor(secNum / 60) % 60
7
14
  const seconds = secNum % 60
8
15
 
9
- return [hours, minutes, seconds]
16
+ let hms = [hours, minutes, seconds]
10
17
  .map(v => v < 10 ? '0' + v : v)
11
18
  .filter((v, i) => v !== '00' || i > 0)
12
19
  .join(':')
20
+ if (ms) hms += '+' + padStart(remain, 3, '0')
21
+ return hms
13
22
  }
14
23
 
15
24
  export default secToHms
@@ -0,0 +1,9 @@
1
+ import { Print } from '../lib/print.js'
2
+
3
+ function spinner (options) {
4
+ const print = new Print(options)
5
+ print.setScope(this)
6
+ return print
7
+ }
8
+
9
+ export default spinner
package/boot/index.js CHANGED
@@ -49,8 +49,8 @@ async function boot (cwd) {
49
49
  // boot complete
50
50
  const { runHook, log } = scope.bajo.helper
51
51
  await runHook('bajo:bootComplete')
52
- const elapsed = (new Date() - scope.bajo.runAt).toLocaleString()
53
- log.info('Boot process completed in %sms', elapsed)
52
+ const elapsed = new Date() - scope.bajo.runAt
53
+ log.info('Boot process completed in %s', scope.bajo.helper.secToHms(elapsed, true))
54
54
  // run tool
55
55
  await runTool.call(scope)
56
56
  return scope
@@ -0,0 +1,8 @@
1
+ import dayjs from 'dayjs'
2
+ import utc from 'dayjs/plugin/utc.js'
3
+ import customParseFormat from 'dayjs/plugin/customParseFormat.js'
4
+
5
+ dayjs.extend(utc)
6
+ dayjs.extend(customParseFormat)
7
+
8
+ export default dayjs
package/boot/lib/print.js CHANGED
@@ -1,82 +1,141 @@
1
- import bora from './bora.js'
2
1
  import Sprintf from 'sprintf-js'
3
- import { isPlainObject, get, isEmpty } from 'lodash-es'
2
+ import ora from 'ora'
3
+ import { isPlainObject, get } from 'lodash-es'
4
4
  import defaultsDeep from '../helper/defaults-deep.js'
5
- import getPluginName from '../helper/get-plugin-name.js'
6
5
 
7
6
  const { sprintf } = Sprintf
8
7
 
9
- class Print {
10
- constructor (scope) {
11
- this.scope = scope
8
+ export class Print {
9
+ constructor (opts = {}) {
10
+ this.opts = opts
11
+ this.startTime = null
12
12
  }
13
13
 
14
- _prep (params) {
15
- const [msg, ...args] = params
14
+ setOpts (args = []) {
15
+ const { getConfig } = this.scope.bajo.helper
16
+ const config = getConfig()
16
17
  let opts = {}
17
18
  if (isPlainObject(args.slice(-1)[0])) opts = args.pop()
18
- opts = defaultsDeep(opts, { type: 'bora', exit: false, skipSilent: false })
19
- this.opts = opts
20
- this.opts.ns = this.opts.ns ?? ['bajoI18N']
21
- this.opts.pkg = this.opts.pkg ?? getPluginName.call(this.scope, 2)
22
- this.args = args
23
- this.msg = msg
19
+ this.opts.isLog = !config.tool
20
+ if (this.opts.isLog) this.opts.isEnabled = false
21
+ this.opts.isSilent = !!(config.silent || this.opts.isSilent)
22
+ this.opts = defaultsDeep(opts, this.opts)
24
23
  }
25
24
 
26
- formatMsg (params) {
27
- this._prep(params)
28
- if (isEmpty(this.msg)) return ''
29
- const transHandler = get(this, 'scope.bajo.transHandler')
30
- const dayjs = get(this, 'scope.bajo.helper')
31
- if (transHandler) this.msg = transHandler.call(this, { msg: this.msg, params: this.args, options: this.opts })
32
- else this.msg = sprintf(this.msg, ...this.args)
33
- if (this.opts.showDatetime && dayjs) this.msg = `[${dayjs().toISOString()}] ${this.msg}`
34
- return this.msg
25
+ setScope (scope) {
26
+ this.scope = scope
27
+ const { dayjs } = this.scope.bajo.helper
28
+ this.startTime = dayjs()
29
+ this.setOpts()
30
+ this.ora = ora(this.opts)
35
31
  }
36
32
 
37
- __ (...params) {
38
- return this.formatMsg(params)
33
+ setText (text, ...args) {
34
+ // const { dayjs } = this.scope.bajo.helper
35
+ text = this.__(text, ...args)
36
+ this.setOpts(args)
37
+ const prefixes = []
38
+ const texts = []
39
+ // if (this.opts.showDatetime) prefixes.push('[' + dayjs().toISOString() + ']')
40
+ if (this.opts.showCounter) texts.push('[' + this.getElapsed() + ']')
41
+ if (prefixes.length > 0) this.ora.prefixText = this.ora.prefixText + prefixes.join(' ')
42
+ if (texts.length > 0) text = texts.join(' ') + ' ' + text
43
+ if (this.opts.isLog) this.info(text, ...args)
44
+ else this.ora.text = text
45
+ return this
39
46
  }
40
47
 
41
- output (params, boraMethod = 'succeed', logMethod = 'info', consoleMethod = 'log') {
42
- this.formatMsg(params)
43
- if (isEmpty(this.msg)) return ''
44
- switch (this.opts.type) {
45
- case 'bora': bora.call(this.scope, this.opts.ns, this.opts)[boraMethod](this.msg, ...this.args); break
46
- case 'log': this.scope.bajo.helper.log[logMethod](this.msg, ...this.args, this.opts); break
47
- default: console[consoleMethod](this.msg)
48
+ __ (text, ...args) {
49
+ if (text) {
50
+ const i18n = get(this, 'scope.bajoI18N.instance')
51
+ if (i18n) {
52
+ if (isPlainObject(args[0])) text = i18n.t(text, args[0])
53
+ else text = i18n.t(text, { ns: this.ns, postProcess: 'sprintf', sprintf: args })
54
+ } else text = sprintf(text, ...args)
48
55
  }
49
- if (this.opts.exit) process.exit()
56
+ return text
50
57
  }
51
58
 
52
- fail (...params) {
53
- this.output(params, 'fail', 'error', 'error')
59
+ getElapsed (unit = 'hms') {
60
+ const { dayjs, secToHms } = this.scope.bajo.helper
61
+ const u = unit === 'hms' ? 'second' : unit
62
+ const elapsed = dayjs().diff(this.startTime, u)
63
+ return unit === 'hms' ? secToHms(elapsed) : elapsed
54
64
  }
55
65
 
56
- succeed (...params) {
57
- this.output(params, 'succeed', 'info')
66
+ start (text, ...args) {
67
+ this.setOpts(args)
68
+ if (this.opts.isLog) {
69
+ this.ora.start()
70
+ this.info(text, ...args)
71
+ return this
72
+ }
73
+ this.setText(text, ...args)
74
+ this.ora.start()
75
+ return this
58
76
  }
59
77
 
60
- warn (...params) {
61
- this.output(params, 'warn', 'warn')
78
+ stop () {
79
+ this.ora.stop()
80
+ return this
62
81
  }
63
82
 
64
- info (...params) {
65
- this.output(params, 'info')
83
+ succeed (text, ...args) {
84
+ const { log } = this.scope.bajo.helper
85
+ if (this.opts.isLog) return log.info(text, ...args)
86
+ this.setText(text, ...args)
87
+ this.ora.succeed()
88
+ return this
66
89
  }
67
90
 
68
- fatal (...params) {
69
- this.output(params, 'fatal', 'error', 'error')
70
- process.exit(1)
91
+ fail (text, ...args) {
92
+ const { log } = this.scope.bajo.helper
93
+ if (this.opts.isLog) return log.error(text, ...args)
94
+ this.setText(text, ...args)
95
+ this.ora.fail()
96
+ return this
97
+ }
98
+
99
+ warn (text, ...args) {
100
+ const { log } = this.scope.bajo.helper
101
+ if (this.opts.isLog) return log.warn(text, ...args)
102
+ this.setText(text, ...args)
103
+ this.ora.warn()
104
+ return this
71
105
  }
72
106
 
73
- bora (...params) {
74
- let ns = getPluginName.call(this.scope, 2)
75
- if (ns === 'bajo') ns = 'bajoI18N'
76
- return bora.call(this.scope, ns, ...params)
107
+ info (text, ...args) {
108
+ const { log } = this.scope.bajo.helper
109
+ if (this.opts.isLog) return log.info(text, ...args)
110
+ this.setText(text, ...args)
111
+ this.ora.info()
112
+ return this
113
+ }
114
+
115
+ clear () {
116
+ this.ora.clear()
117
+ return this
118
+ }
119
+
120
+ render () {
121
+ this.ora.render()
122
+ return this
123
+ }
124
+
125
+ fatal (text, ...args) {
126
+ const { log } = this.scope.bajo.helper
127
+ if (this.opts.isLog) {
128
+ log.fatal(text, ...args)
129
+ process.exit(1)
130
+ }
131
+ this.setText(text, ...args)
132
+ this.ora.fail()
133
+ process.exit(1)
77
134
  }
78
135
  }
79
136
 
80
- export default function () {
81
- return new Print(this)
137
+ export default function (options) {
138
+ const print = new Print(options)
139
+ print.setScope(this)
140
+ return print
82
141
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bajo",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "description": "A framework to build a giant monstrous app rapidly",
5
5
  "main": "boot/index.js",
6
6
  "scripts": {
@@ -38,6 +38,7 @@
38
38
  "fs-extra": "^11.1.1",
39
39
  "global-modules-path": "^3.0.0",
40
40
  "lodash-es": "^4.17.21",
41
+ "ms": "^2.1.3",
41
42
  "nanoid": "^4.0.2",
42
43
  "node-fetch": "^3.3.1",
43
44
  "omit-deep": "^0.3.0",
package/boot/lib/bora.js DELETED
@@ -1,113 +0,0 @@
1
- import Sprintf from 'sprintf-js'
2
- import ora from 'ora'
3
- import { last, isPlainObject, get, isString } from 'lodash-es'
4
-
5
- const { sprintf } = Sprintf
6
-
7
- class Bora {
8
- constructor (ns, ...args) {
9
- this.ns = ns
10
- const l = last(args)
11
- let opts = {}
12
- if (isPlainObject(l)) opts = args.pop()
13
- this.opts = opts
14
- this.ora = ora(this.opts)
15
- this.args = args
16
- this.startTime = null
17
- }
18
-
19
- setScope (scope) {
20
- this.scope = scope
21
- const { getConfig, dayjs } = this.scope.bajo.helper
22
- this.startTime = dayjs()
23
- const config = getConfig()
24
- let silent = !!config.silent
25
- if (this.opts.skipSilent) silent = false
26
- this.ora.isSilent = silent
27
- const [text, ...params] = this.args
28
- this.setText(text, ...params)
29
- }
30
-
31
- setText (text, ...args) {
32
- const { dayjs } = this.scope.bajo.helper
33
- if (isString(text)) {
34
- const i18n = get(this, 'scope.bajoI18N.instance')
35
- if (i18n) {
36
- if (isPlainObject(args[0])) text = i18n.t(text, args[0])
37
- else text = i18n.t(text, { ns: this.ns, postProcess: 'sprintf', sprintf: args })
38
- } else text = sprintf(text, ...args)
39
- let opts = last(args)
40
- if (!isPlainObject(opts)) opts = {}
41
- const texts = []
42
- if (this.opts.showDatetime || opts.showDatetime) texts.push('[' + dayjs().toISOString() + ']')
43
- if (this.opts.showCounter || opts.showCounter) texts.push('[' + this.getElapsed() + ']')
44
- texts.push(text)
45
- this.ora.text = texts.join(' ')
46
- }
47
- return this
48
- }
49
-
50
- getElapsed (unit = 'hms') {
51
- const { dayjs, secToHms } = this.scope.bajo.helper
52
- const u = unit === 'hms' ? 'second' : unit
53
- const elapsed = dayjs().diff(this.startTime, u)
54
- return unit === 'hms' ? secToHms(elapsed) : elapsed
55
- }
56
-
57
- start (text, ...args) {
58
- this.setText(text, ...args)
59
- this.ora.start()
60
- return this
61
- }
62
-
63
- stop () {
64
- this.ora.stop()
65
- return this
66
- }
67
-
68
- succeed (text, ...args) {
69
- this.setText(text, ...args)
70
- this.ora.succeed()
71
- return this
72
- }
73
-
74
- fail (text, ...args) {
75
- this.setText(text, ...args)
76
- this.ora.fail()
77
- return this
78
- }
79
-
80
- warn (text, ...args) {
81
- this.setText(text, ...args)
82
- this.ora.warn()
83
- return this
84
- }
85
-
86
- info (text, ...args) {
87
- this.setText(text, ...args)
88
- this.ora.info()
89
- return this
90
- }
91
-
92
- clear () {
93
- this.ora.clear()
94
- return this
95
- }
96
-
97
- render () {
98
- this.ora.render()
99
- return this
100
- }
101
-
102
- fatal (text, ...args) {
103
- this.setText(text, ...args)
104
- this.ora.fail()
105
- process.exit(1)
106
- }
107
- }
108
-
109
- export default function (ns, ...args) {
110
- const bora = new Bora(ns, ...args)
111
- bora.setScope(this)
112
- return bora
113
- }