bajo-extra 0.2.8 → 0.2.10

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.
@@ -1,32 +1,59 @@
1
- async function fetchAndSave ({ source = {}, converter, coll, current = {}, options = {} } = {}) {
2
- const { print, setImmediate, importPkg, getConfig } = this.bajo.helper
3
- const { isEmpty, isFunction } = await importPkg('lodash-es')
1
+ async function batching ({ source = {}, converter, coll, current = {}, options = {}, spin } = {}) {
2
+ const { setImmediate, importPkg, print } = this.bajo.helper
3
+ const { isEmpty, isFunction, set } = await importPkg('lodash-es')
4
4
  const { fetch } = this.bajoExtra.helper
5
5
  const { recordCreate, recordFind, recordUpdate, validationErrorMessage } = this.bajoDb.helper
6
- const config = getConfig()
7
- const opts = { type: options.returnEarly ? 'log' : 'bora', pkg: options.pkg }
8
- const showDatetime = !config.tool
9
- const spinner = print.bora('Fetching starts...', { showCounter: true, showDatetime, isSilent: options.returnEarly }).start()
10
- if (options.returnEarly) print.succeed('Fetching starts...', opts)
11
6
  const resp = await fetch(source.url, source.options ?? {})
12
- if (isEmpty(resp)) spinner.fatal('No result from server, aborted!')
7
+ if (isEmpty(resp)) spin.fatal('No result from server, aborted!')
13
8
  if (source.abort) {
14
9
  const aborted = await source.abort.call(this, resp)
15
- if (aborted) spinner.fatal(aborted)
10
+ if (aborted) spin.fatal(aborted)
16
11
  }
17
12
  let count = 0
13
+ const stat = { created: 0, updated: 0, skipped: 0, error: 0 }
18
14
  const iterator = isFunction(source.iterator) ? await source.iterator.call(this, resp) : resp[source.iterator]
19
- spinner.setText('Got %d records, processing...', iterator.length)
15
+ if (iterator.length === 0) {
16
+ print.warn('No records to process, abort')
17
+ return 0
18
+ }
19
+ spin.setText('Got %d records, processing...', iterator.length)
20
20
  for (let r of iterator) {
21
21
  await setImmediate()
22
22
  if (converter) r = await converter.call(this, r, options)
23
- if (isEmpty(r)) continue
23
+ if (isEmpty(r)) {
24
+ stat.skipped++
25
+ continue
26
+ }
24
27
  try {
25
- await recordCreate(coll, r)
26
- if (current.coll && current.query) {
27
- const query = await current.query.call(this, r)
28
+ let existing
29
+ let record
30
+ let method
31
+ options.checkUnique = options.checkUnique ?? 'id'
32
+ if (['unique', 'upsert'].includes(options.mode)) {
33
+ const query = isFunction(options.checkUnique) ? await options.checkUnique.call(this, r, options) : set({}, options.checkUnique, r[options.checkUnique])
34
+ const resp = await recordFind(coll, { query, limit: 1 }, { skipCache: true })
35
+ if (resp.length > 0) existing = resp[0]
36
+ }
37
+ if (existing) {
38
+ if (options.mode === 'upsert') {
39
+ const body = options.updateConverter ? await options.updateConverter.call(this, r, options) : r
40
+ record = await recordUpdate(coll, existing.id, body)
41
+ method = 'updated'
42
+ stat.updated++
43
+ } else {
44
+ stat.skipped++
45
+ print.warn(`[${spin.getElapsed()}] Record %s exists, skipped`, JSON.stringify(r))
46
+ method = 'skipped'
47
+ }
48
+ } else {
49
+ stat.created++
50
+ record = await recordCreate(coll, r)
51
+ method = 'created'
52
+ }
53
+ if (record && current.coll && current.query) {
54
+ const query = await current.query.call(this, { body: r, record, options })
28
55
  const recs = await recordFind(current.coll, { query }, { skipCache: true })
29
- const rc = current.converter ? await current.converter.call(this, r, options) : r
56
+ const rc = current.converter ? await current.converter.call(this, { body: r, record, options }) : r
30
57
  if (rc) {
31
58
  if (recs.length > 0) {
32
59
  const id = recs[0].id
@@ -36,17 +63,42 @@ async function fetchAndSave ({ source = {}, converter, coll, current = {}, optio
36
63
  }
37
64
  }
38
65
  }
39
- if (options.printCount && (count % options.printCount === 0)) print.succeed(`[${spinner.getElapsed()}] Batch line %d/%d`, count, iterator.length, opts)
40
- else spinner.setText('Record %d/%d...', count, iterator.length)
66
+ if (options.printCount && options.printCount < count && (count % options.printCount === 0)) print.succeed('[%s] Processed %d/%d', spin.getElapsed(), count, iterator.length)
67
+ else if (!spin.opts.isLog) spin.setText('Record %d/%d...', count, iterator.length, method)
41
68
  count++
42
69
  } catch (err) {
43
70
  console.log(err)
44
- spinner.setText(validationErrorMessage(err) + ', continue')
71
+ spin.setText(validationErrorMessage(err) + ', continue')
72
+ }
73
+ }
74
+ print.succeed('[%s] %d/%d records processed', spin.getElapsed(), count, iterator.length)
75
+ print.succeed('[%s] Created: %d, Updated: %d, Skipped: %d', spin.getElapsed(), stat.created, stat.updated, stat.skipped)
76
+ return iterator.length
77
+ }
78
+
79
+ async function fetchAndSave ({ source = {}, converter, coll, current = {}, options = {} } = {}) {
80
+ const { print, spinner } = this.bajo.helper
81
+ source.options = source.options ?? {}
82
+ source.options.params = source.options.params ?? {}
83
+ if (options.batch) {
84
+ print.info('Batch starting')
85
+ const spin = spinner({ showCounter: true }).start('Fetching starts...')
86
+ let step = 1
87
+ for (;;) {
88
+ print.info('[%s] Fetch batch #%d', spin.getElapsed(), step)
89
+ const newSource = await options.batch.call(this, source)
90
+ if (newSource) source = newSource
91
+ const length = await batching.call(this, { source, converter, coll, current, options, spin })
92
+ if (length === 0) {
93
+ print.info('All done!')
94
+ break
95
+ }
96
+ step++
45
97
  }
98
+ } else {
99
+ const spin = spinner({ showCounter: true }).start('Fetching starts...')
100
+ await batching.call(this, { source, converter, coll, current, options, spin })
46
101
  }
47
- spinner.info(`${count}/${iterator.length} records processed`)
48
- if (options.returnEarly) print.info(`${count}/${iterator.length} records processed`, opts)
49
- else spinner.succeed('Done!')
50
102
  }
51
103
 
52
104
  export default fetchAndSave
@@ -1,26 +1,21 @@
1
1
  import Path from 'path'
2
2
 
3
- function makeProgress (spinner) {
3
+ function makeProgress (spin) {
4
4
  return async function ({ batchNo, batchTotal, data } = {}) {
5
5
  if (batchTotal === 0) return
6
- spinner.setText('Batch %d of %d (%d records)', batchNo, batchTotal, data.length)
6
+ spin.setText('Batch %d of %d (%d records)', batchNo, batchTotal, data.length)
7
7
  }
8
8
  }
9
9
 
10
- async function exportTo ({ path, args, returnEarly }) {
11
- const { importPkg, print, dayjs, getConfig, importModule } = this.bajo.helper
10
+ async function exportTo ({ path, args }) {
11
+ const { importPkg, print, dayjs, getConfig, importModule, spinner } = this.bajo.helper
12
12
  const { isEmpty, map } = await importPkg('lodash-es')
13
13
  const [input, select] = await importPkg('bajo-cli:@inquirer/input',
14
14
  'bajo-cli:@inquirer/select')
15
- if (!this.bajoDb) {
16
- print.fail('Bajo DB isn\'t loaded', { exit: !returnEarly })
17
- if (returnEarly) return
18
- }
15
+ const config = getConfig()
16
+ if (!this.bajoDb) return print.fail('Bajo DB isn\'t loaded', { exit: config.tool })
19
17
  const schemas = map(this.bajoDb.schemas, 'name')
20
- if (isEmpty(schemas)) {
21
- print.fail('No schema found!', { exit: !returnEarly })
22
- if (returnEarly) return
23
- }
18
+ if (isEmpty(schemas)) return print.fail('No schema found!', { exit: config.tool })
24
19
  let [coll, dest, query] = args
25
20
  if (isEmpty(coll)) {
26
21
  coll = await select({
@@ -40,8 +35,8 @@ async function exportTo ({ path, args, returnEarly }) {
40
35
  message: print.__('Please enter a query (if any):')
41
36
  })
42
37
  }
43
- const spinner = print.bora('Exporting...').start()
44
- const progressFn = makeProgress.call(this, spinner)
38
+ const spin = spinner().start('Exporting...')
39
+ const progressFn = makeProgress.call(this, spin)
45
40
  const cfg = getConfig('bajoDb', { full: true })
46
41
  const { batch } = getConfig()
47
42
  const start = await importModule(`${cfg.dir.pkg}/bajo/start.js`)
@@ -50,10 +45,10 @@ async function exportTo ({ path, args, returnEarly }) {
50
45
  try {
51
46
  const filter = { query }
52
47
  const result = await this.bajoExtra.helper.exportTo(coll, dest, { filter, batch, progressFn })
53
- spinner.succeed('%d records successfully exported to \'%s\'', result.count, Path.resolve(result.file))
48
+ spin.succeed('%d records successfully exported to \'%s\'', result.count, Path.resolve(result.file))
54
49
  } catch (err) {
55
50
  console.log(err)
56
- spinner.fail('Error: %s', err.message, { exit: !returnEarly })
51
+ spin.fail('Error: %s', err.message, { exit: config.tool })
57
52
  }
58
53
  }
59
54
 
@@ -1,25 +1,20 @@
1
1
  import Path from 'path'
2
2
 
3
- function makeProgress (spinner) {
3
+ function makeProgress (spin) {
4
4
  return async function ({ batchNo, data } = {}) {
5
- spinner.setText('Batch %d (%d records)', batchNo, data.length)
5
+ spin.setText('Batch %d (%d records)', batchNo, data.length)
6
6
  }
7
7
  }
8
8
 
9
- async function importFrom ({ path, args, returnEarly }) {
10
- const { importPkg, print, importModule, getConfig } = this.bajo.helper
9
+ async function importFrom ({ path, args }) {
10
+ const { importPkg, print, importModule, getConfig, spinner } = this.bajo.helper
11
11
  const { isEmpty, map } = await importPkg('lodash-es')
12
12
  const [input, select, confirm] = await importPkg('bajo-cli:@inquirer/input',
13
13
  'bajo-cli:@inquirer/select', 'bajo-cli:@inquirer/confirm')
14
- if (!this.bajoDb) {
15
- print.fail('Bajo DB isn\'t loaded', { exit: !returnEarly })
16
- if (returnEarly) return
17
- }
14
+ const config = getConfig()
15
+ if (!this.bajoDb) return print.fail('Bajo DB isn\'t loaded', { exit: config.tool })
18
16
  const schemas = map(this.bajoDb.schemas, 'name')
19
- if (isEmpty(schemas)) {
20
- print.fail('No schema found!', { exit: !returnEarly })
21
- if (returnEarly) return
22
- }
17
+ if (isEmpty(schemas)) return print.fail('No schema found!', { exit: config.tool })
23
18
  let [dest, coll] = args
24
19
  if (isEmpty(dest)) {
25
20
  dest = await input({
@@ -37,12 +32,9 @@ async function importFrom ({ path, args, returnEarly }) {
37
32
  message: print.__('You\'re about to replace ALL records with the new ones. Are you really sure?'),
38
33
  default: false
39
34
  })
40
- if (!answer) {
41
- print.fail('Aborted!', { exit: !returnEarly })
42
- if (returnEarly) return
43
- }
44
- const spinner = print.bora('Importing...').start()
45
- const progressFn = makeProgress.call(this, spinner)
35
+ if (!answer) return print.fail('Aborted!', { exit: config.tool })
36
+ const spin = spinner().start('Importing...')
37
+ const progressFn = makeProgress.call(this, spin)
46
38
  const cfg = getConfig('bajoDb', { full: true })
47
39
  const { batch } = getConfig()
48
40
  const start = await importModule(`${cfg.dir.pkg}/bajo/start.js`)
@@ -50,9 +42,9 @@ async function importFrom ({ path, args, returnEarly }) {
50
42
  await start.call(this, connection.name)
51
43
  try {
52
44
  const result = await this.bajoExtra.helper.importFrom(dest, coll, { batch, progressFn })
53
- spinner.succeed('%d records successfully imported from \'%s\'', result.count, Path.resolve(result.file))
45
+ spin.succeed('%d records successfully imported from \'%s\'', result.count, Path.resolve(result.file))
54
46
  } catch (err) {
55
- spinner.fail('Error: %s', err.message, { exit: !returnEarly })
47
+ spin.fail('Error: %s', err.message, { exit: config.tool })
56
48
  }
57
49
  }
58
50
 
package/bajoCli/tool.js CHANGED
@@ -1,8 +1,8 @@
1
- async function tool ({ path, args = [], returnEarly }) {
1
+ async function tool ({ path, args = [] }) {
2
2
  const { currentLoc } = this.bajo.helper
3
3
  const { runToolMethod } = this.bajoCli.helper
4
4
  const options = { demonize: ['shell'] }
5
- await runToolMethod({ path, args, dir: `${currentLoc(import.meta).dir}/tool`, options, returnEarly })
5
+ await runToolMethod({ path, args, dir: `${currentLoc(import.meta).dir}/tool`, options })
6
6
  }
7
7
 
8
8
  export default tool
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bajo-extra",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "Extra package for Bajo Framework",
5
5
  "main": "index.js",
6
6
  "scripts": {