waibu-db 2.0.0 → 2.1.0

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 (124) hide show
  1. package/.github/FUNDING.yml +13 -0
  2. package/.github/workflows/repo-lockdown.yml +24 -0
  3. package/.jsdoc.conf.json +45 -0
  4. package/LICENSE +0 -0
  5. package/README.md +31 -9
  6. package/docs/WaibuDb.html +3 -0
  7. package/docs/data/search.json +1 -0
  8. package/docs/fonts/Inconsolata-Regular.ttf +0 -0
  9. package/docs/fonts/OpenSans-Regular.ttf +0 -0
  10. package/docs/fonts/WorkSans-Bold.ttf +0 -0
  11. package/docs/global.html +3 -0
  12. package/docs/index.html +3 -0
  13. package/docs/index.js.html +225 -0
  14. package/docs/scripts/core.js +726 -0
  15. package/docs/scripts/core.min.js +23 -0
  16. package/docs/scripts/resize.js +90 -0
  17. package/docs/scripts/search.js +265 -0
  18. package/docs/scripts/search.min.js +6 -0
  19. package/docs/scripts/third-party/Apache-License-2.0.txt +202 -0
  20. package/docs/scripts/third-party/fuse.js +9 -0
  21. package/docs/scripts/third-party/hljs-line-num-original.js +369 -0
  22. package/docs/scripts/third-party/hljs-line-num.js +1 -0
  23. package/docs/scripts/third-party/hljs-original.js +5171 -0
  24. package/docs/scripts/third-party/hljs.js +1 -0
  25. package/docs/scripts/third-party/popper.js +5 -0
  26. package/docs/scripts/third-party/tippy.js +1 -0
  27. package/docs/scripts/third-party/tocbot.js +672 -0
  28. package/docs/scripts/third-party/tocbot.min.js +1 -0
  29. package/docs/static/bitcoin.jpeg +0 -0
  30. package/docs/static/home.md +23 -0
  31. package/docs/static/logo-ecosystem.png +0 -0
  32. package/docs/static/logo.png +0 -0
  33. package/docs/styles/clean-jsdoc-theme-base.css +1159 -0
  34. package/docs/styles/clean-jsdoc-theme-dark.css +412 -0
  35. package/docs/styles/clean-jsdoc-theme-light.css +482 -0
  36. package/docs/styles/clean-jsdoc-theme-scrollbar.css +30 -0
  37. package/docs/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
  38. package/docs/styles/clean-jsdoc-theme.min.css +1 -0
  39. package/extend/bajo/hook/waibu-rest-api@after-init.js +3 -2
  40. package/extend/bajo/intl/en-US.json +0 -0
  41. package/extend/bajo/intl/id.json +0 -0
  42. package/extend/bajoTemplate/partial/crud/_add-attachment.html +0 -0
  43. package/extend/bajoTemplate/partial/crud/_add-btns.html +2 -2
  44. package/extend/bajoTemplate/partial/crud/_addons.html +0 -0
  45. package/extend/bajoTemplate/partial/crud/_details-attachment.html +0 -0
  46. package/extend/bajoTemplate/partial/crud/_details-btns.html +0 -0
  47. package/extend/bajoTemplate/partial/crud/_edit-attachment.html +0 -0
  48. package/extend/bajoTemplate/partial/crud/_edit-btns.html +2 -0
  49. package/extend/bajoTemplate/partial/crud/_list-attachment.html +0 -0
  50. package/extend/bajoTemplate/partial/crud/_list-btns.html +0 -0
  51. package/extend/bajoTemplate/partial/crud/_list-footer.html +0 -0
  52. package/extend/bajoTemplate/partial/crud/add-handler.html +0 -0
  53. package/extend/bajoTemplate/partial/crud/details-handler.html +0 -0
  54. package/extend/bajoTemplate/partial/crud/edit-handler.html +0 -0
  55. package/extend/bajoTemplate/partial/crud/list-handler.html +1 -1
  56. package/extend/bajoTemplate/partial/crud/~echarts-window.html +0 -0
  57. package/extend/bajoTemplate/template/crud/add.html +0 -0
  58. package/extend/bajoTemplate/template/crud/details.html +0 -0
  59. package/extend/bajoTemplate/template/crud/edit.html +0 -0
  60. package/extend/bajoTemplate/template/crud/list.html +0 -0
  61. package/extend/bajoTemplate/template/disabled.html +0 -0
  62. package/extend/waibuBootstrap/theme/component/factory/btn-add.js +1 -1
  63. package/extend/waibuBootstrap/theme/component/factory/btn-back.js +2 -2
  64. package/extend/waibuBootstrap/theme/component/factory/btn-clone.js +1 -1
  65. package/extend/waibuBootstrap/theme/component/factory/btn-columns.js +3 -3
  66. package/extend/waibuBootstrap/theme/component/factory/btn-delete.js +2 -2
  67. package/extend/waibuBootstrap/theme/component/factory/btn-details.js +2 -2
  68. package/extend/waibuBootstrap/theme/component/factory/btn-edit.js +2 -2
  69. package/extend/waibuBootstrap/theme/component/factory/btn-export.js +1 -1
  70. package/extend/waibuBootstrap/theme/component/factory/echarts-bar.js +2 -2
  71. package/extend/waibuBootstrap/theme/component/factory/echarts-pie.js +2 -2
  72. package/extend/waibuBootstrap/theme/component/factory/echarts.js +3 -3
  73. package/extend/waibuBootstrap/theme/component/factory/form.js +2 -2
  74. package/extend/waibuBootstrap/theme/component/factory/pagination.js +3 -3
  75. package/extend/waibuBootstrap/theme/component/factory/query.js +4 -4
  76. package/extend/waibuBootstrap/theme/component/factory/recs-info.js +2 -2
  77. package/extend/waibuBootstrap/theme/component/factory/table.js +11 -11
  78. package/extend/waibuBootstrap/theme/component/wdb-base.js +0 -0
  79. package/extend/waibuMpa/extend/waibuAdmin/route/@model/@action.js +0 -0
  80. package/extend/waibuRestApi/route/@model/@id/get.js +1 -1
  81. package/extend/waibuRestApi/route/@model/@id/remove.js +1 -1
  82. package/extend/waibuRestApi/route/@model/@id/update.js +1 -1
  83. package/extend/waibuRestApi/route/@model/create.js +1 -1
  84. package/extend/waibuRestApi/route/@model/find.js +3 -3
  85. package/extend/waibuRestApi/route/@model/stat/@stat/find.js +8 -0
  86. package/index.js +144 -24
  87. package/lib/crud/add-handler.js +10 -9
  88. package/lib/crud/all-handler.js +1 -1
  89. package/lib/crud/delete-handler.js +6 -5
  90. package/lib/crud/details-handler.js +6 -6
  91. package/lib/crud/edit-handler.js +11 -12
  92. package/lib/crud/export-handler.js +5 -5
  93. package/lib/crud/helper/add-ons-handler.js +3 -3
  94. package/lib/crud/helper/attachment-handler.js +2 -2
  95. package/lib/crud/helper/build-params.js +4 -5
  96. package/lib/crud/list-handler.js +5 -5
  97. package/lib/method/count-record.js +9 -0
  98. package/lib/method/create-aggregate.js +13 -0
  99. package/lib/method/create-histogram.js +13 -0
  100. package/lib/method/create-record.js +10 -0
  101. package/lib/method/find-one-record.js +14 -0
  102. package/lib/method/find-record.js +14 -0
  103. package/lib/method/get-record.js +10 -0
  104. package/{method → lib/method}/get-schema-ext.js +16 -17
  105. package/lib/method/remove-record.js +9 -0
  106. package/lib/method/update-record.js +10 -0
  107. package/lib/prep-crud.js +9 -10
  108. package/package.json +15 -4
  109. package/wiki/CHANGES.md +5 -0
  110. package/wiki/CONFIG.md +3 -0
  111. package/wiki/CONTRIBUTING.md +5 -0
  112. package/method/format-record.js +0 -41
  113. package/method/get-lookup-data.js +0 -13
  114. package/method/get-params.js +0 -18
  115. package/method/method-map.js +0 -9
  116. package/method/record/count.js +0 -10
  117. package/method/record/create.js +0 -11
  118. package/method/record/find-one.js +0 -15
  119. package/method/record/find.js +0 -15
  120. package/method/record/get.js +0 -11
  121. package/method/record/remove.js +0 -10
  122. package/method/record/update.js +0 -11
  123. package/method/stat/aggregate.js +0 -14
  124. package/method/stat/histogram.js +0 -14
@@ -1,28 +1,27 @@
1
1
  import attachmentHandler from './helper/attachment-handler.js'
2
2
 
3
3
  async function editHandler ({ req, reply, model, id, params = {}, template, addOnsHandler, templateDisabled = 'waibuDb.template:/disabled.html', options = {} } = {}) {
4
- const { pascalCase } = this.lib.aneka
4
+ const { pascalCase } = this.app.lib.aneka
5
5
  const { getPluginDataDir } = this.app.bajo
6
- const { recordUpdate, recordGet, getSchemaExt } = this.app.waibuDb
6
+ const { updateRecord, getRecord, getSchemaExt } = this.app.waibuDb
7
7
  const { buildUrl } = this.app.waibuMpa
8
- const { fs } = this.lib
9
- const { defaultsDeep } = this.lib.aneka
10
- const { merge, isEmpty, omit } = this.lib._
8
+ const { fs } = this.app.lib
9
+ const { defaultsDeep } = this.app.lib.aneka
10
+ const { merge, isEmpty, omit } = this.app.lib._
11
11
  const opts = {}
12
12
  let error
13
13
  let resp
14
14
  let form
15
- model = model ?? pascalCase(req.params.model)
15
+ model = pascalCase(model ?? req.params.model)
16
16
  const { schema } = await getSchemaExt(model, 'edit', merge({}, { params }, options))
17
17
  if (schema.disabled.includes('update')) return await reply.view(templateDisabled, { action: 'edit' })
18
18
  // req.query.attachment = true
19
19
  opts.fields = schema.view.fields
20
20
  id = id ?? req.params.id ?? req.query.id
21
- if (req.method === 'GET') {
22
- const old = await recordGet({ model, req, id, options: opts })
23
- form = defaultsDeep(req.body, old.data)
24
- } else {
25
- form = omit(req.body, ['_action', '_value'])
21
+ const old = await getRecord({ model, req, id, options: opts })
22
+ form = defaultsDeep(req.body, old.data)
23
+ if (req.method !== 'GET') {
24
+ form = omit(form, ['_action', '_value'])
26
25
  if (req.body._action === 'removeatt' && !isEmpty(req.body._value)) {
27
26
  const root = `${getPluginDataDir('dobo')}/attachment`
28
27
  for (const item of req.body._value) {
@@ -34,7 +33,7 @@ async function editHandler ({ req, reply, model, id, params = {}, template, addO
34
33
  if (req && req.flash) req.flash('notify', req.t('attachmentRemoved'))
35
34
  } else {
36
35
  try {
37
- resp = await recordUpdate({ model, req, id, reply, options: opts })
36
+ resp = await updateRecord({ model, req, id, reply, options: opts })
38
37
  form = resp.data
39
38
  return reply.redirectTo(buildUrl({ url: req.url, base: req.params.base ?? req.query.base ?? 'list', params: { page: 1 }, exclude: ['id'] }))
40
39
  } catch (err) {
@@ -2,16 +2,16 @@ import prepCrud from '../prep-crud.js'
2
2
 
3
3
  async function exportHandler ({ req, reply, model, params = {}, templateDisabled = 'waibuDb.template:/disabled.html', options = {} } = {}) {
4
4
  const { getPlugin } = this.app.bajo
5
- const { dayjs } = this.lib
6
- const { omit, kebabCase, get, merge } = this.lib._
7
- const { pascalCase } = this.lib.aneka
5
+ const { dayjs } = this.app.lib
6
+ const { omit, kebabCase, get, merge } = this.app.lib._
7
+ const { pascalCase } = this.app.lib.aneka
8
8
  const { getSchemaExt } = this.app.waibuDb
9
9
  const { buildUrl } = this.app.waibuMpa
10
10
  const { pushDownload } = getPlugin('sumba')
11
- model = model ?? pascalCase(req.params.model)
11
+ model = pascalCase(model ?? req.params.model)
12
12
  const { schema } = await getSchemaExt(model, 'add', merge({}, { params }, options))
13
13
  if (schema.disabled.includes('find')) return await reply.view(templateDisabled, { action: 'list' })
14
- const data = prepCrud.call(getPlugin('waibuDb'), { model, req, reply, args: ['model'] })
14
+ const data = await prepCrud.call(getPlugin('waibuDb'), { model, req, reply, args: ['model'] })
15
15
  data.opts = omit(data.opts, ['req', 'reply'])
16
16
  const source = `${this.name}:/export-handler`
17
17
  const worker = 'waibuDb:exportData'
@@ -1,8 +1,8 @@
1
1
  async function addOnsHandler ({ req, reply, data, schema, options = {} }) {
2
2
  const { escape } = this.app.waibu
3
3
  const { base64JsonEncode } = this.app.waibuMpa
4
- const { statAggregate } = this.app.waibuDb
5
- const { get, map, pick, pullAt } = this.lib._
4
+ const { createAggregate } = this.app.waibuDb
5
+ const { get, map, pick, pullAt } = this.app.lib._
6
6
  const opts = map(get(schema, 'view.stat.aggregate', []), item => {
7
7
  const dbOpts = pick(item, ['fields', 'group', 'aggregate'])
8
8
  const name = item.name ?? `field.${item.fields[0]}`
@@ -13,7 +13,7 @@ async function addOnsHandler ({ req, reply, data, schema, options = {} }) {
13
13
  for (const idx in opts) {
14
14
  const o = opts[idx]
15
15
  try {
16
- const resp = await statAggregate({ model: schema.name, req, reply, options: o.dbOpts })
16
+ const resp = await createAggregate({ model: schema.name, req, reply, options: o.dbOpts })
17
17
  const data = []
18
18
  for (const d of resp.data) {
19
19
  const key = o.dbOpts.fields[0]
@@ -1,7 +1,7 @@
1
1
  async function attachmentHandler ({ schema, id, options = {} }) {
2
- const { listAttachments } = this.app.dobo
3
2
  if (!schema.view.attachment) return []
4
- return await listAttachments({ model: schema.name, id })
3
+ const model = this.app.dobo.getModel(schema.name)
4
+ return await model.listAttachment({ id })
5
5
  }
6
6
 
7
7
  export default attachmentHandler
@@ -1,11 +1,10 @@
1
1
  function buildParams ({ model, req, reply, action, options = {} }) {
2
- const { camelCase, kebabCase, map, upperFirst, get } = this.lib._
3
- const { getSchema } = this.app.dobo
2
+ const { camelCase, kebabCase, map, upperFirst, get } = this.app.lib._
4
3
  const [, ...names] = map(kebabCase(model).split('-'), n => upperFirst(n))
5
- const schema = getSchema(camelCase(model), false)
6
- const modelTitle = this.app[schema.ns].title + ': ' + req.t(camelCase(names.join(' ')))
4
+ const mdl = this.app.dobo.getModel(model)
5
+ const modelTitle = this.app[mdl.plugin.ns].title + ': ' + req.t(camelCase(names.join(' ')))
7
6
  const page = {
8
- title: req.t(get(req, 'routeOptions.config.title', this.app[schema.ns].title)),
7
+ title: req.t(get(req, 'routeOptions.config.title', this.app[mdl.plugin.ns].title)),
9
8
  modelTitle
10
9
  }
11
10
  return { page }
@@ -1,9 +1,9 @@
1
1
  async function listHandler ({ req, reply, model, template, params = {}, addOnsHandler, templateDisabled = 'waibuDb.template:/disabled.html', options = {} } = {}) {
2
- const { pascalCase } = this.lib.aneka
3
- const { recordFind, getSchemaExt } = this.app.waibuDb
4
- const { get, merge, isArray, upperFirst } = this.lib._
2
+ const { pascalCase } = this.app.lib.aneka
3
+ const { findRecord, getSchemaExt } = this.app.waibuDb
4
+ const { get, merge, isArray, upperFirst } = this.app.lib._
5
5
  const qsKey = this.app.waibu.config.qsKey
6
- model = model ?? pascalCase(req.params.model)
6
+ model = pascalCase(model ?? req.params.model)
7
7
  const { schema } = await getSchemaExt(model, 'list', merge({}, { params }, options))
8
8
  if (schema.disabled.includes('find')) return await reply.view(templateDisabled, { action: 'list' })
9
9
  for (const key of ['sort', 'limit', 'fields']) {
@@ -13,7 +13,7 @@ async function listHandler ({ req, reply, model, template, params = {}, addOnsHa
13
13
  }
14
14
  if (!req.query[qsKey.page]) req.query[qsKey.page] = 1
15
15
  // req.query.attachment = true
16
- const list = await recordFind({ model, req, options: { count: true, rels: '*' } })
16
+ const list = await findRecord({ model, req, options: { count: true, refs: '*' } })
17
17
  let addOns = []
18
18
  if (addOnsHandler) {
19
19
  addOns = await addOnsHandler.call(this.app[req.ns], { req, reply, params, data: list, schema, options })
@@ -0,0 +1,9 @@
1
+ import prepCrud from '../prep-crud.js'
2
+
3
+ async function countRecord ({ model, req, reply, options = {} }) {
4
+ const { model: mdl, opts, filter } = await prepCrud.call(this, { model, req, reply, options, args: ['model'] })
5
+ const ret = await mdl.countRecord(filter, opts)
6
+ return ret
7
+ }
8
+
9
+ export default countRecord
@@ -0,0 +1,13 @@
1
+ import prepCrud from '../prep-crud.js'
2
+
3
+ async function createAggregate ({ model, req, reply, options = {} }) {
4
+ const { model: mdl, opts, filter } = await prepCrud.call(this, { model, req, reply, options, args: ['model'] })
5
+ const params = {}
6
+ for (const item of ['group', 'field', 'aggregates']) {
7
+ params[item] = options[item] ?? req.params[item] ?? req.query[item]
8
+ }
9
+ params.aggregates = params.aggregates ?? ['count']
10
+ return await mdl.createAggregate(filter, params, opts)
11
+ }
12
+
13
+ export default createAggregate
@@ -0,0 +1,13 @@
1
+ import prepCrud from '../prep-crud.js'
2
+
3
+ async function createHistogram ({ model, req, reply, options = {} }) {
4
+ const { model: mdl, opts, filter } = await prepCrud.call(this, { model, req, reply, options, args: ['model'] })
5
+ const params = {}
6
+ for (const item of ['type', 'group', 'field', 'aggregates']) {
7
+ params[item] = options[item] ?? req.params[item] ?? req.query[item]
8
+ }
9
+ params.aggregates = params.aggregates ?? ['count']
10
+ return await mdl.createHistogram(filter, params, opts)
11
+ }
12
+
13
+ export default createHistogram
@@ -0,0 +1,10 @@
1
+ import prepCrud from '../prep-crud.js'
2
+
3
+ async function createRecord ({ model, req, reply, body, options = {} }) {
4
+ const { model: mdl, input, opts, attachment, stats, mimeType } = await prepCrud.call(this, { model, req, reply, body, options, args: ['model'] })
5
+ const ret = await mdl.createRecord(input, opts)
6
+ if (attachment) ret.data._attachment = await mdl.findAttachment(ret.data.id, { stats, mimeType })
7
+ return ret
8
+ }
9
+
10
+ export default createRecord
@@ -0,0 +1,14 @@
1
+ import prepCrud from '../prep-crud.js'
2
+
3
+ async function findOneRecord ({ model, req, reply, options = {} }) {
4
+ const { model: mdl, opts, filter, attachment, stats, mimeType } = await prepCrud.call(this, { model, req, reply, options, args: ['model'] })
5
+ const ret = await mdl.findOneRecord(filter, opts)
6
+ if (attachment) {
7
+ for (const d of ret.data) {
8
+ d._attachment = await mdl.findAttachment(d.id, { stats, mimeType })
9
+ }
10
+ }
11
+ return ret
12
+ }
13
+
14
+ export default findOneRecord
@@ -0,0 +1,14 @@
1
+ import prepCrud from '../prep-crud.js'
2
+
3
+ async function findRecord ({ model, req, reply, options = {} }) {
4
+ const { model: mdl, opts, filter, attachment, stats, mimeType } = await prepCrud.call(this, { model, req, reply, options, args: ['model'] })
5
+ const ret = await mdl.findRecord(filter, opts)
6
+ if (attachment) {
7
+ for (const d of ret.data) {
8
+ d._attachment = await mdl.findAttachment(d.id, { stats, mimeType })
9
+ }
10
+ }
11
+ return ret
12
+ }
13
+
14
+ export default findRecord
@@ -0,0 +1,10 @@
1
+ import prepCrud from '../prep-crud.js'
2
+
3
+ async function getRecord ({ model, req, reply, id, options = {} }) {
4
+ const { model: mdl, recId, filter, opts } = await prepCrud.call(this, { model, req, reply, id, options, args: ['model', 'id'] })
5
+ filter.query = { $and: [filter.query ?? {}, { id: recId }] }
6
+ const ret = await mdl.findOneRecord(filter, opts)
7
+ return ret
8
+ }
9
+
10
+ export default getRecord
@@ -5,8 +5,8 @@ const defReadonly = ['id', 'createdAt', 'updatedAt']
5
5
  const defFormatter = {}
6
6
 
7
7
  function getCommons (action, schema, ext, options = {}) {
8
- const { defaultsDeep } = this.lib.aneka
9
- const { merge, map, get, set, without, uniq, pull } = this.lib._
8
+ const { defaultsDeep } = this.app.lib.aneka
9
+ const { merge, map, get, set, without, uniq, pull } = this.app.lib._
10
10
  const calcFields = get(ext, `view.${action}.calcFields`, get(ext, 'common.calcFields', []))
11
11
  const forceVisible = get(ext, `view.${action}.forceVisible`, get(ext, 'common.forceVisible', []))
12
12
  const widget = defaultsDeep(get(ext, `view.${action}.widget`), get(ext, 'common.widget', {}))
@@ -54,7 +54,7 @@ function getCommons (action, schema, ext, options = {}) {
54
54
  }
55
55
 
56
56
  function autoLayout ({ action, schema, ext, layout }) {
57
- const { forOwn, keys } = this.lib._
57
+ const { forOwn, keys } = this.app.lib._
58
58
  const matches = ['id', 'createdAt', 'updatedAt']
59
59
  const meta = []
60
60
  const general = []
@@ -70,8 +70,8 @@ function autoLayout ({ action, schema, ext, layout }) {
70
70
  }
71
71
 
72
72
  function customLayout ({ action, schema, ext, layout, readonly }) {
73
- const { defaultsDeep } = this.lib.aneka
74
- const { isEmpty } = this.lib._
73
+ const { defaultsDeep } = this.app.lib.aneka
74
+ const { isEmpty } = this.app.lib._
75
75
  const items = [...layout]
76
76
  for (const item of items) {
77
77
  for (const idx in item.fields) {
@@ -88,8 +88,8 @@ function customLayout ({ action, schema, ext, layout, readonly }) {
88
88
  }
89
89
 
90
90
  function applyLayout (action, schema, ext) {
91
- const { defaultsDeep } = this.lib.aneka
92
- const { set, get, isEmpty, find, kebabCase } = this.lib._
91
+ const { defaultsDeep } = this.app.lib.aneka
92
+ const { set, get, isEmpty, find, kebabCase } = this.app.lib._
93
93
  const { fields, card, calcFields } = getCommons.call(this, action, schema, ext)
94
94
  const layout = get(ext, `view.${action}.layout`, get(ext, 'common.layout', []))
95
95
  const readonly = get(ext, `view.${action}.readonly`, get(ext, 'common.readonly', defReadonly))
@@ -140,7 +140,7 @@ function applyLayout (action, schema, ext) {
140
140
 
141
141
  const handler = {
142
142
  list: async function (schema, ext, options) {
143
- const { get, set } = this.lib._
143
+ const { get, set } = this.app.lib._
144
144
  const { fields } = getCommons.call(this, 'list', schema, ext, options)
145
145
  const qsFields = []
146
146
  for (const f of get(schema, 'view.qs.fields', '').split(',')) {
@@ -167,19 +167,18 @@ const handler = {
167
167
  }
168
168
  }
169
169
 
170
- async function getSchemaExt (model, view, options = {}) {
170
+ async function getSchemaExt (modelName, view, options = {}) {
171
171
  const { readConfig } = this.app.bajo
172
- const { defaultsDeep } = this.lib.aneka
173
- const { getSchema } = this.app.dobo
174
- const { pick } = this.lib._
172
+ const { defaultsDeep } = this.app.lib.aneka
173
+ const { pick } = this.app.lib._
175
174
 
176
- let schema = getSchema(model)
177
- const base = path.basename(schema.file, path.extname(schema.file))
178
- let ext = await readConfig(`${schema.ns}:/extend/waibuDb/schema/${base}.*`, { ignoreError: true, options })
179
- const over = await readConfig(`main:/extend/waibuDb/extend/${schema.ns}/schema/${base}.*`, { ignoreError: true, options })
175
+ const model = this.app.dobo.getModel(modelName)
176
+ const schema = pick(model, ['name', 'properties', 'indexes', 'disabled', 'attachment', 'sortables', 'view', 'hidden'])
177
+ const base = path.basename(model.file, path.extname(model.file))
178
+ let ext = await readConfig(`${model.plugin.ns}:/extend/waibuDb/schema/${base}.*`, { ignoreError: true, options })
179
+ const over = await readConfig(`main:/extend/waibuDb/extend/${model.plugin.ns}/schema/${base}.*`, { ignoreError: true, options })
180
180
  ext = defaultsDeep(options.schema ?? {}, over, ext)
181
181
  await handler[view].call(this, schema, ext, options)
182
- schema = pick(schema, ['name', 'properties', 'indexes', 'disabled', 'attachment', 'sortables', 'view'])
183
182
  return { schema, ext }
184
183
  }
185
184
 
@@ -0,0 +1,9 @@
1
+ import prepCrud from '../prep-crud.js'
2
+
3
+ async function removeRecord ({ model, req, reply, id, options = {} }) {
4
+ const { model: mdl, recId, opts } = await prepCrud.call(this, { model, req, reply, id, options, args: ['model', 'id'] })
5
+ const result = await mdl.removeRecord(recId, opts)
6
+ return result
7
+ }
8
+
9
+ export default removeRecord
@@ -0,0 +1,10 @@
1
+ import prepCrud from '../prep-crud.js'
2
+
3
+ async function updateRecord ({ model, req, reply, id, body, options = {} }) {
4
+ const { model: mdl, input, opts, recId, attachment, stats, mimeType } = await prepCrud.call(this, { model, req, reply, body, id, options, args: ['model', 'id'] })
5
+ const ret = await mdl.updateRecord(recId, input, opts)
6
+ if (attachment) ret.data._attachment = await mdl.findAttachment(id, { stats, mimeType })
7
+ return ret
8
+ }
9
+
10
+ export default updateRecord
package/lib/prep-crud.js CHANGED
@@ -1,8 +1,7 @@
1
- function prepCrud ({ model, body, id, req, reply, options = {}, args }) {
1
+ async function prepCrud ({ model, body, id, req, reply, options = {}, args }) {
2
2
  const { parseFilter } = this.app.waibu
3
- const { buildQuery, getInfo } = this.app.dobo
4
- const { pascalCase } = this.lib.aneka
5
- const { cloneDeep, has } = this.lib._
3
+ const { pascalCase } = this.app.lib.aneka
4
+ const { cloneDeep, has, pick } = this.app.lib._
6
5
  const cfgWeb = this.app.waibu.getConfig()
7
6
  const opts = cloneDeep(options)
8
7
  const params = this.getParams(req, ...args)
@@ -20,18 +19,18 @@ function prepCrud ({ model, body, id, req, reply, options = {}, args }) {
20
19
  mimeType = mimeType ?? req.query.mimeType
21
20
 
22
21
  const recId = id ?? params.id ?? req.query.id
23
- const name = pascalCase(model ?? params.model)
24
- const { schema } = getInfo(name)
25
- const input = body ?? params.body
22
+ model = model ?? pascalCase(params.model)
23
+ const mdl = this.app.dobo.getModel(model)
24
+ const input = await mdl.sanitizeBody({ body: body ?? params.body, partial: true, strict: true })
25
+
26
26
  opts.bboxLatField = req.query[cfgWeb.qsKey.bboxLatField]
27
27
  opts.bboxLngField = req.query[cfgWeb.qsKey.bboxLngField]
28
- const filter = parseFilter(req)
28
+ const filter = pick(parseFilter(req), ['query', 'match', 'limit', 'sort', 'page', 'skip'])
29
29
  if (options.query) filter.query = cloneDeep(options.query)
30
30
  if (options.limit) filter.limit = options.limit
31
31
  if (options.sort) filter.sort = options.sort
32
32
  if (options.page) filter.page = options.page
33
- filter.query = buildQuery({ filter, schema })
34
- return { name, recId, input, opts, filter, attachment, stats, mimeType }
33
+ return { model: mdl, recId, input, opts, filter, attachment, stats, mimeType }
35
34
  }
36
35
 
37
36
  export default prepCrud
package/package.json CHANGED
@@ -1,14 +1,21 @@
1
1
  {
2
2
  "name": "waibu-db",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "DB Helper",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
7
+ "build-doc": "jsdoc -c .jsdoc.conf.json",
8
+ "test": "mocha"
8
9
  },
9
10
  "type": "module",
10
11
  "bajo": {
11
- "type": "plugin"
12
+ "type": "plugin",
13
+ "alias": "wdb",
14
+ "dependencies": [
15
+ "dobo",
16
+ "waibu",
17
+ "dobo-extra"
18
+ ]
12
19
  },
13
20
  "repository": {
14
21
  "type": "git",
@@ -29,5 +36,9 @@
29
36
  "bugs": {
30
37
  "url": "https://github.com/ardhi/waibu-db/issues"
31
38
  },
32
- "homepage": "https://github.com/ardhi/waibu-db#readme"
39
+ "homepage": "https://github.com/ardhi/waibu-db#readme",
40
+ "devDependencies": {
41
+ "clean-jsdoc-theme": "^4.3.0",
42
+ "jsdoc-plugin-intersection": "^1.0.4"
43
+ }
33
44
  }
@@ -0,0 +1,5 @@
1
+ # Changes
2
+
3
+ ## 2025-12-28
4
+
5
+ - [2.1.0] Ported to ```bajo@2.2.x``` & ```dobo@2.2.x``` specs
package/wiki/CONFIG.md ADDED
@@ -0,0 +1,3 @@
1
+ # Config Object
2
+
3
+ TBD
@@ -0,0 +1,5 @@
1
+ # Contributing
2
+
3
+ Thanks very much to everyone who wants to join as a contributor, but I have committed to devoting 100% of my time to this project. Therefore, I'm currently unable to accept pull requests from anyone until the project is large enough for me to manage it independently.
4
+
5
+ However, I am available if you encounter any bugs that require immediate fixes. Please report your issues in a GitHub issue, and I'll try to address them promptly. I'm also open to criticism and suggestions for improvements or requests for new features.
@@ -1,41 +0,0 @@
1
- async function formatRow ({ data, req, schema, options = {} }) {
2
- const { get, find, isFunction, cloneDeep } = this.lib._
3
- const { format, callHandler } = this.app.bajo
4
- const { escape } = this.app.waibu
5
- const fields = get(schema, 'view.fields', Object.keys(schema.properties))
6
- const rec = cloneDeep(data)
7
- for (const f of fields) {
8
- if (f === '_rel') continue
9
- let prop = find(schema.properties, { name: f })
10
- if (!prop) prop = find(schema.view.calcFields, { name: f })
11
- if (!prop) continue
12
- const opts = {
13
- lang: options.lang ?? (req ? req.lang : undefined),
14
- longitude: ['lng', 'longitude'].includes(f),
15
- latitude: ['lat', 'latitude'].includes(f),
16
- speed: ['speed'].includes(f),
17
- degree: ['course', 'heading'].includes(f),
18
- distance: ['distance'].includes(f)
19
- }
20
- rec[f] = format(data[f], prop.type, opts)
21
- const vf = get(schema, `view.valueFormatter.${f}`)
22
- if (vf) {
23
- if (isFunction(vf)) rec[f] = await vf.call(this, data[f], data)
24
- else rec[f] = await callHandler(vf, { req, value: data[f], data })
25
- } else if (['string', 'text'].includes(prop.type)) rec[f] = escape(rec[f])
26
- }
27
- return rec
28
- }
29
-
30
- async function formatRecord ({ data, req, schema, options = {} }) {
31
- const { isArray } = this.lib._
32
- if (!isArray(data)) return await formatRow.call(this, { data, req, schema, options })
33
- const items = []
34
- for (const d of data) {
35
- const item = await formatRow.call(this, { data: d, req, schema, options })
36
- items.push(item)
37
- }
38
- return items
39
- }
40
-
41
- export default formatRecord
@@ -1,13 +0,0 @@
1
- async function getLookupData ({ model, req, data, id = 'id', field, query }) {
2
- const { set, map } = this.lib._
3
- const $in = map(data, id)
4
- const q = query ?? set({}, field, { $in })
5
- const options = {
6
- dataOnly: true,
7
- limit: -1,
8
- query: q
9
- }
10
- return await this.recordFind({ model, req, options })
11
- }
12
-
13
- export default getLookupData
@@ -1,18 +0,0 @@
1
- function getParams (req, ...items) {
2
- const { map, trim, get } = this.lib._
3
- let fields
4
- req.query = req.query ?? {}
5
- req.params = req.params ?? {}
6
- if (req.query.fields) fields = map((req.query.fields ?? '').split(','), i => trim(i))
7
- const params = {
8
- fields,
9
- count: get(this, 'config.dbModel.count', false),
10
- body: req.body
11
- }
12
- items.forEach(i => {
13
- params[i] = req.params[i]
14
- })
15
- return params
16
- }
17
-
18
- export default getParams
@@ -1,9 +0,0 @@
1
- const methodMap = {
2
- create: 'POST',
3
- find: 'GET',
4
- get: 'GET',
5
- update: 'PUT',
6
- remove: 'DELETE'
7
- }
8
-
9
- export default methodMap
@@ -1,10 +0,0 @@
1
- import prepCrud from '../../lib/prep-crud.js'
2
-
3
- async function count ({ model, req, reply, options = {} }) {
4
- const { recordCount } = this.app.dobo
5
- const { name, opts, filter } = prepCrud.call(this, { model, req, reply, options, args: ['model'] })
6
- const ret = await recordCount(name, filter, opts)
7
- return ret
8
- }
9
-
10
- export default count
@@ -1,11 +0,0 @@
1
- import prepCrud from '../../lib/prep-crud.js'
2
-
3
- async function create ({ model, req, reply, body, options = {} }) {
4
- const { recordCreate, attachmentFind } = this.app.dobo
5
- const { name, input, opts, attachment, stats, mimeType } = prepCrud.call(this, { model, req, reply, body, options, args: ['model'] })
6
- const ret = await recordCreate(name, input, opts)
7
- if (attachment) ret.data._attachment = await attachmentFind(name, ret.data.id, { stats, mimeType })
8
- return ret
9
- }
10
-
11
- export default create
@@ -1,15 +0,0 @@
1
- import prepCrud from '../../lib/prep-crud.js'
2
-
3
- async function find ({ model, req, reply, options = {} }) {
4
- const { recordFindOne, attachmentFind } = this.app.dobo
5
- const { name, opts, filter, attachment, stats, mimeType } = prepCrud.call(this, { model, req, reply, options, args: ['model'] })
6
- const ret = await recordFindOne(name, filter, opts)
7
- if (attachment) {
8
- for (const d of ret.data) {
9
- d._attachment = await attachmentFind(name, d.id, { stats, mimeType })
10
- }
11
- }
12
- return ret
13
- }
14
-
15
- export default find
@@ -1,15 +0,0 @@
1
- import prepCrud from '../../lib/prep-crud.js'
2
-
3
- async function find ({ model, req, reply, options = {} }) {
4
- const { recordFind, attachmentFind } = this.app.dobo
5
- const { name, opts, filter, attachment, stats, mimeType } = prepCrud.call(this, { model, req, reply, options, args: ['model'] })
6
- const ret = await recordFind(name, filter, opts)
7
- if (attachment) {
8
- for (const d of ret.data) {
9
- d._attachment = await attachmentFind(name, d.id, { stats, mimeType })
10
- }
11
- }
12
- return ret
13
- }
14
-
15
- export default find
@@ -1,11 +0,0 @@
1
- import prepCrud from '../../lib/prep-crud.js'
2
-
3
- async function get ({ model, req, reply, id, options = {} }) {
4
- const { recordFindOne } = this.app.dobo
5
- const { name, recId, filter, opts } = prepCrud.call(this, { model, req, reply, id, options, args: ['model', 'id'] })
6
- filter.query = { $and: [filter.query ?? {}, { id: recId }] }
7
- const ret = await recordFindOne(name, filter, opts)
8
- return ret
9
- }
10
-
11
- export default get
@@ -1,10 +0,0 @@
1
- import prepCrud from '../../lib/prep-crud.js'
2
-
3
- async function remove ({ model, req, reply, id, options = {} }) {
4
- const { recordRemove } = this.app.dobo
5
- const { name, recId, opts } = prepCrud.call(this, { model, req, reply, id, options, args: ['model', 'id'] })
6
- const result = await recordRemove(name, recId, opts)
7
- return result
8
- }
9
-
10
- export default remove
@@ -1,11 +0,0 @@
1
- import prepCrud from '../../lib/prep-crud.js'
2
-
3
- async function update ({ model, req, reply, id, body, options = {} }) {
4
- const { recordUpdate, attachmentFind } = this.app.dobo
5
- const { name, input, opts, recId, attachment, stats, mimeType } = prepCrud.call(this, { model, req, reply, body, id, options, args: ['model', 'id'] })
6
- const ret = await recordUpdate(name, recId, input, opts)
7
- if (attachment) ret.data._attachment = await attachmentFind(name, id, { stats, mimeType })
8
- return ret
9
- }
10
-
11
- export default update
@@ -1,14 +0,0 @@
1
- import prepCrud from '../../lib/prep-crud.js'
2
-
3
- async function aggregate ({ model, req, reply, options = {} }) {
4
- const { statAggregate } = this.app.dobo
5
- const { parseFilter } = this.app.waibu
6
- const { name, opts } = prepCrud.call(this, { model, req, reply, options, args: ['model'] })
7
- for (const item of ['group', 'aggregate']) {
8
- opts[item] = options[item] ?? req.params[item] ?? req.query[item]
9
- }
10
- opts.aggregate = opts.aggregate ?? 'count'
11
- return await statAggregate(name, parseFilter(req), opts)
12
- }
13
-
14
- export default aggregate