expressa 2.0.18 → 2.0.20

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 (258) hide show
  1. package/.circleci/config.yml +21 -21
  2. package/.eslintrc.json +29 -29
  3. package/LICENSE +21 -21
  4. package/README.md +137 -137
  5. package/auth/index.js +76 -76
  6. package/auth/jwt.js +31 -31
  7. package/controllers/collections.js +260 -260
  8. package/controllers/install.js +105 -105
  9. package/controllers/status.js +43 -43
  10. package/controllers/users.js +52 -52
  11. package/cypress/fixtures/example.json +4 -4
  12. package/cypress/integration/0_install_spec.js +8 -8
  13. package/cypress/integration/custom_collections.js +30 -28
  14. package/cypress/integration/home.js +9 -9
  15. package/cypress/integration/settings.js +34 -34
  16. package/cypress/integration/users.js +61 -61
  17. package/cypress/plugins/index.js +17 -17
  18. package/cypress/support/commands.js +69 -54
  19. package/cypress/support/index.js +20 -20
  20. package/cypress/support/util.js +10 -10
  21. package/cypress.config.js +18 -0
  22. package/cypress.json +4 -4
  23. package/db/cached.js +40 -40
  24. package/db/file.js +112 -112
  25. package/db/memory.js +79 -79
  26. package/db/mongo.js +86 -86
  27. package/db/postgres.js +93 -93
  28. package/doc/authentication.md +38 -38
  29. package/doc/automatic-fields.md +12 -12
  30. package/doc/blogexample.md +16 -16
  31. package/doc/custom-endpoints.md +20 -20
  32. package/doc/database.md +23 -23
  33. package/doc/development.md +33 -33
  34. package/doc/listeners.md +103 -103
  35. package/doc/modules.md +8 -8
  36. package/doc/permissions.md +14 -14
  37. package/doc/relationships.md +65 -65
  38. package/doc/testing.md +47 -47
  39. package/doc/uploading-files.md +53 -53
  40. package/index.js +297 -297
  41. package/listeners.js +65 -65
  42. package/listeners_collection_permissions.js +29 -29
  43. package/listeners_users.js +96 -96
  44. package/listeners_validation.js +43 -43
  45. package/middleware/logging.js +30 -30
  46. package/middleware/permissions.js +41 -41
  47. package/modules/access_keys/access_keys.js +32 -32
  48. package/modules/admin/.babelrc +19 -19
  49. package/modules/admin/.editorconfig +14 -14
  50. package/modules/admin/.eslintignore +5 -5
  51. package/modules/admin/.eslintrc.js +197 -197
  52. package/modules/admin/.postcssrc.js +10 -10
  53. package/modules/admin/.travis.yml +5 -5
  54. package/modules/admin/LICENSE +21 -21
  55. package/modules/admin/README.md +88 -88
  56. package/modules/admin/build/build.js +46 -45
  57. package/modules/admin/build/check-versions.js +64 -64
  58. package/modules/admin/build/utils.js +109 -108
  59. package/modules/admin/build/vue-loader.conf.js +5 -5
  60. package/modules/admin/build/webpack.base.conf.js +112 -112
  61. package/modules/admin/build/webpack.dev.conf.js +95 -95
  62. package/modules/admin/build/webpack.prod.conf.js +112 -112
  63. package/modules/admin/config/dev.env.js +8 -8
  64. package/modules/admin/config/index.js +86 -86
  65. package/modules/admin/config/prod.env.js +5 -5
  66. package/modules/admin/dist/css/197.7a90435e.css +7 -0
  67. package/modules/admin/dist/css/197.7a90435e.css.gz +0 -0
  68. package/modules/admin/dist/css/430.8c9b0482.css +8 -0
  69. package/modules/admin/dist/css/430.8c9b0482.css.gz +0 -0
  70. package/modules/admin/dist/css/451.c6646d20.css +1 -0
  71. package/modules/admin/dist/css/451.c6646d20.css.gz +0 -0
  72. package/modules/admin/dist/css/566.7a90435e.css +7 -0
  73. package/modules/admin/dist/css/566.7a90435e.css.gz +0 -0
  74. package/modules/admin/dist/css/569.f7d5c7d5.css +37 -0
  75. package/modules/admin/dist/css/569.f7d5c7d5.css.gz +0 -0
  76. package/modules/admin/dist/css/572.74d8e965.css +34 -0
  77. package/modules/admin/dist/css/572.74d8e965.css.gz +0 -0
  78. package/modules/admin/dist/css/651.e946bda7.css +6 -0
  79. package/modules/admin/dist/css/651.e946bda7.css.gz +0 -0
  80. package/modules/admin/dist/css/750.4086915d.css +2 -0
  81. package/modules/admin/dist/css/750.4086915d.css.gz +0 -0
  82. package/modules/admin/dist/css/950.1fd9d57c.css +7 -0
  83. package/modules/admin/dist/css/950.1fd9d57c.css.gz +0 -0
  84. package/modules/admin/dist/css/app.eba5f5e2.css +592 -0
  85. package/modules/admin/dist/css/app.eba5f5e2.css.gz +0 -0
  86. package/modules/admin/dist/index.html +1 -1
  87. package/modules/admin/dist/static/fonts/element-icons.313f7da.woff +0 -0
  88. package/modules/admin/dist/static/fonts/element-icons.4520188.ttf +0 -0
  89. package/modules/admin/dist/static/js/197.e511d91e.js +1 -0
  90. package/modules/admin/dist/static/js/197.e511d91e.js.gz +0 -0
  91. package/modules/admin/dist/static/js/430.b3941f30.js +1 -0
  92. package/modules/admin/dist/static/js/430.b3941f30.js.gz +0 -0
  93. package/modules/admin/dist/static/js/451.645974a8.js +1 -0
  94. package/modules/admin/dist/static/js/451.645974a8.js.gz +0 -0
  95. package/modules/admin/dist/static/js/460.962d5bc0.js +1 -0
  96. package/modules/admin/dist/static/js/460.962d5bc0.js.gz +0 -0
  97. package/modules/admin/dist/static/js/550.f27feb23.js +1 -0
  98. package/modules/admin/dist/static/js/550.f27feb23.js.gz +0 -0
  99. package/modules/admin/dist/static/js/556.1e08866a.js +1 -0
  100. package/modules/admin/dist/static/js/556.1e08866a.js.gz +0 -0
  101. package/modules/admin/dist/static/js/569.0fecfbee.js +1 -0
  102. package/modules/admin/dist/static/js/569.0fecfbee.js.gz +0 -0
  103. package/modules/admin/dist/static/js/572.13392e1d.js +1 -0
  104. package/modules/admin/dist/static/js/572.13392e1d.js.gz +0 -0
  105. package/modules/admin/dist/static/js/603.7b34a650.js +1 -0
  106. package/modules/admin/dist/static/js/603.7b34a650.js.gz +0 -0
  107. package/modules/admin/dist/static/js/651.564b24b6.js +1 -0
  108. package/modules/admin/dist/static/js/651.564b24b6.js.gz +0 -0
  109. package/modules/admin/dist/static/js/653.02ec1098.js +1 -0
  110. package/modules/admin/dist/static/js/653.02ec1098.js.gz +0 -0
  111. package/modules/admin/dist/static/js/750.50c950da.js +1 -0
  112. package/modules/admin/dist/static/js/750.50c950da.js.gz +0 -0
  113. package/modules/admin/dist/static/js/950.d4ff0a18.js +1 -0
  114. package/modules/admin/dist/static/js/950.d4ff0a18.js.gz +0 -0
  115. package/modules/admin/dist/static/js/app.ea86ae11.js +2 -0
  116. package/modules/admin/dist/static/js/{chunk-libs.06c38828.js.LICENSE.txt → app.ea86ae11.js.LICENSE.txt} +15 -18
  117. package/modules/admin/dist/static/js/app.ea86ae11.js.LICENSE.txt.gz +0 -0
  118. package/modules/admin/dist/static/js/app.ea86ae11.js.gz +0 -0
  119. package/modules/admin/index.html +16 -16
  120. package/modules/admin/package.json +101 -101
  121. package/modules/admin/src/App.vue +11 -11
  122. package/modules/admin/src/api/login.js +26 -26
  123. package/modules/admin/src/api/table.js +9 -9
  124. package/modules/admin/src/components/Breadcrumb/index.vue +79 -79
  125. package/modules/admin/src/components/Hamburger/index.vue +62 -62
  126. package/modules/admin/src/components/JSONEditor.vue +180 -180
  127. package/modules/admin/src/components/SvgIcon/index.vue +43 -43
  128. package/modules/admin/src/icons/index.js +9 -9
  129. package/modules/admin/src/icons/svgo.yml +22 -22
  130. package/modules/admin/src/main.js +42 -42
  131. package/modules/admin/src/permission.js +49 -49
  132. package/modules/admin/src/router/index.js +200 -200
  133. package/modules/admin/src/store/getters.js +11 -11
  134. package/modules/admin/src/store/index.js +17 -17
  135. package/modules/admin/src/store/modules/app.js +43 -43
  136. package/modules/admin/src/store/modules/user.js +104 -104
  137. package/modules/admin/src/styles/element-ui.scss +29 -29
  138. package/modules/admin/src/styles/index.scss +78 -78
  139. package/modules/admin/src/styles/mixin.scss +27 -27
  140. package/modules/admin/src/styles/sidebar.scss +133 -133
  141. package/modules/admin/src/styles/transition.scss +46 -46
  142. package/modules/admin/src/styles/variables.scss +4 -4
  143. package/modules/admin/src/utils/auth.js +15 -15
  144. package/modules/admin/src/utils/index.js +74 -74
  145. package/modules/admin/src/utils/request.js +48 -48
  146. package/modules/admin/src/utils/validate.js +31 -31
  147. package/modules/admin/src/views/404.vue +235 -235
  148. package/modules/admin/src/views/Dev.vue +33 -33
  149. package/modules/admin/src/views/EditDocument.vue +121 -116
  150. package/modules/admin/src/views/Endpoints.vue +279 -279
  151. package/modules/admin/src/views/Home.vue +84 -84
  152. package/modules/admin/src/views/Install.vue +79 -79
  153. package/modules/admin/src/views/ListDocuments.vue +72 -72
  154. package/modules/admin/src/views/ListDocuments2.vue +467 -462
  155. package/modules/admin/src/views/ManageListeners.vue +67 -67
  156. package/modules/admin/src/views/ManageMiddleware.vue +43 -43
  157. package/modules/admin/src/views/ManagePermissions.vue +75 -75
  158. package/modules/admin/src/views/ViewRequest.vue +77 -77
  159. package/modules/admin/src/views/form/index.vue +91 -91
  160. package/modules/admin/src/views/layout/Layout.vue +69 -69
  161. package/modules/admin/src/views/layout/components/AppMain.vue +41 -41
  162. package/modules/admin/src/views/layout/components/Navbar.vue +97 -97
  163. package/modules/admin/src/views/layout/components/Sidebar/Item.vue +29 -29
  164. package/modules/admin/src/views/layout/components/Sidebar/Link.vue +39 -39
  165. package/modules/admin/src/views/layout/components/Sidebar/SidebarItem.vue +103 -103
  166. package/modules/admin/src/views/layout/components/Sidebar/index.vue +62 -62
  167. package/modules/admin/src/views/layout/components/index.js +3 -3
  168. package/modules/admin/src/views/layout/mixin/ResizeHandler.js +41 -41
  169. package/modules/admin/src/views/login/index.vue +195 -195
  170. package/modules/admin/src/views/tree/index.vue +77 -77
  171. package/modules/collections/collections.js +39 -39
  172. package/modules/core/core.js +197 -197
  173. package/modules/logging/logging.js +88 -88
  174. package/modules/permissions/permissions.js +106 -106
  175. package/package.json +59 -59
  176. package/scripts/expressa +12 -12
  177. package/scripts/run_cypress_tests.sh +36 -6
  178. package/scripts/run_db_tests.sh +8 -8
  179. package/test/0-install.js +96 -96
  180. package/test/collections.js +431 -431
  181. package/test/collections.querying.js +288 -288
  182. package/test/db.js +258 -258
  183. package/test/db.strings.js +73 -73
  184. package/test/db.updating.js +144 -144
  185. package/test/logging.js +29 -29
  186. package/test/test.js +93 -93
  187. package/test/testserver.js +17 -17
  188. package/test/testutils.js +136 -136
  189. package/test/users.js +425 -425
  190. package/util.js +522 -522
  191. package/modules/admin/dist/index.html.gz +0 -0
  192. package/modules/admin/dist/static/css/app.9dd57eea.css +0 -1
  193. package/modules/admin/dist/static/css/app.9dd57eea.css.gz +0 -0
  194. package/modules/admin/dist/static/css/chunk-5061.ce0e4bdb.css +0 -1
  195. package/modules/admin/dist/static/css/chunk-5061.ce0e4bdb.css.gz +0 -0
  196. package/modules/admin/dist/static/css/chunk-5b97.7f9cb53e.css +0 -1
  197. package/modules/admin/dist/static/css/chunk-5b97.7f9cb53e.css.gz +0 -0
  198. package/modules/admin/dist/static/css/chunk-621e.b826be8d.css +0 -1
  199. package/modules/admin/dist/static/css/chunk-621e.b826be8d.css.gz +0 -0
  200. package/modules/admin/dist/static/css/chunk-656b.9c828b00.css +0 -1
  201. package/modules/admin/dist/static/css/chunk-656b.9c828b00.css.gz +0 -0
  202. package/modules/admin/dist/static/css/chunk-7291.13514e45.css +0 -0
  203. package/modules/admin/dist/static/css/chunk-7291.13514e45.css.gz +0 -0
  204. package/modules/admin/dist/static/css/chunk-7f29.9c828b00.css +0 -1
  205. package/modules/admin/dist/static/css/chunk-7f29.9c828b00.css.gz +0 -0
  206. package/modules/admin/dist/static/css/chunk-9a95.c647a2ef.css +0 -1
  207. package/modules/admin/dist/static/css/chunk-9a95.c647a2ef.css.gz +0 -0
  208. package/modules/admin/dist/static/css/chunk-b423.5f239333.css +0 -0
  209. package/modules/admin/dist/static/css/chunk-b423.5f239333.css.gz +0 -0
  210. package/modules/admin/dist/static/css/chunk-bd5f.aefa49d7.css +0 -1
  211. package/modules/admin/dist/static/css/chunk-bd5f.aefa49d7.css.gz +0 -0
  212. package/modules/admin/dist/static/css/chunk-e374.025d58bb.css +0 -1
  213. package/modules/admin/dist/static/css/chunk-e374.025d58bb.css.gz +0 -0
  214. package/modules/admin/dist/static/css/chunk-elementUI.3d004d9f.css +0 -1
  215. package/modules/admin/dist/static/css/chunk-elementUI.3d004d9f.css.gz +0 -0
  216. package/modules/admin/dist/static/css/chunk-f075.3a895a1e.css +0 -1
  217. package/modules/admin/dist/static/css/chunk-f075.3a895a1e.css.gz +0 -0
  218. package/modules/admin/dist/static/css/chunk-libs.327ad89e.css +0 -14
  219. package/modules/admin/dist/static/css/chunk-libs.327ad89e.css.gz +0 -0
  220. package/modules/admin/dist/static/fonts/element-icons.6f0a763.ttf +0 -0
  221. package/modules/admin/dist/static/js/app.e9461593.js +0 -1
  222. package/modules/admin/dist/static/js/app.e9461593.js.gz +0 -0
  223. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js +0 -2
  224. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.LICENSE.txt +0 -13
  225. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.LICENSE.txt.gz +0 -0
  226. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.gz +0 -0
  227. package/modules/admin/dist/static/js/chunk-5061.83e6ccfa.js +0 -1
  228. package/modules/admin/dist/static/js/chunk-5061.83e6ccfa.js.gz +0 -0
  229. package/modules/admin/dist/static/js/chunk-5b97.ac360086.js +0 -1
  230. package/modules/admin/dist/static/js/chunk-5b97.ac360086.js.gz +0 -0
  231. package/modules/admin/dist/static/js/chunk-5e17.a2b69611.js +0 -1
  232. package/modules/admin/dist/static/js/chunk-5e17.a2b69611.js.gz +0 -0
  233. package/modules/admin/dist/static/js/chunk-621e.ccf42393.js +0 -1
  234. package/modules/admin/dist/static/js/chunk-621e.ccf42393.js.gz +0 -0
  235. package/modules/admin/dist/static/js/chunk-656b.9d5b03c0.js +0 -1
  236. package/modules/admin/dist/static/js/chunk-656b.9d5b03c0.js.gz +0 -0
  237. package/modules/admin/dist/static/js/chunk-7291.590524e9.js +0 -1
  238. package/modules/admin/dist/static/js/chunk-7291.590524e9.js.gz +0 -0
  239. package/modules/admin/dist/static/js/chunk-7f29.6ffc142e.js +0 -1
  240. package/modules/admin/dist/static/js/chunk-7f29.6ffc142e.js.gz +0 -0
  241. package/modules/admin/dist/static/js/chunk-9a95.bdd76583.js +0 -1
  242. package/modules/admin/dist/static/js/chunk-9a95.bdd76583.js.gz +0 -0
  243. package/modules/admin/dist/static/js/chunk-b423.387c504c.js +0 -1
  244. package/modules/admin/dist/static/js/chunk-b423.387c504c.js.gz +0 -0
  245. package/modules/admin/dist/static/js/chunk-bd5f.e9509f10.js +0 -1
  246. package/modules/admin/dist/static/js/chunk-bd5f.e9509f10.js.gz +0 -0
  247. package/modules/admin/dist/static/js/chunk-e374.7c87a0dd.js +0 -1
  248. package/modules/admin/dist/static/js/chunk-e374.7c87a0dd.js.gz +0 -0
  249. package/modules/admin/dist/static/js/chunk-e7c3.e5df8ceb.js +0 -1
  250. package/modules/admin/dist/static/js/chunk-e7c3.e5df8ceb.js.gz +0 -0
  251. package/modules/admin/dist/static/js/chunk-elementUI.b0c99c08.js +0 -1
  252. package/modules/admin/dist/static/js/chunk-elementUI.b0c99c08.js.gz +0 -0
  253. package/modules/admin/dist/static/js/chunk-f075.315ceec1.js +0 -1
  254. package/modules/admin/dist/static/js/chunk-f075.315ceec1.js.gz +0 -0
  255. package/modules/admin/dist/static/js/chunk-libs.06c38828.js +0 -2
  256. package/modules/admin/dist/static/js/chunk-libs.06c38828.js.LICENSE.txt.gz +0 -0
  257. package/modules/admin/dist/static/js/chunk-libs.06c38828.js.gz +0 -0
  258. /package/modules/admin/dist/static/img/{404.a57b6f3.png → 404.4cf6930.png} +0 -0
package/db/file.js CHANGED
@@ -1,112 +1,112 @@
1
- const Store = require('jfs')
2
- const debug = require('debug')('expressa')
3
- const { promisify } = require('util')
4
- Store.prototype.allAsync = promisify(Store.prototype.all)
5
- Store.prototype.getAsync = promisify(Store.prototype.get)
6
- Store.prototype.saveAsync = promisify(Store.prototype.save)
7
-
8
- const util = require('../util')
9
-
10
- module.exports = function (settings, collection) {
11
- const store = new Store((settings.file_storage_path || 'data') + '/' + collection, {
12
- pretty: true,
13
- saveId: '_id'
14
- })
15
-
16
- return {
17
- init: function () {},
18
- all: async function () {
19
- return this.find({})
20
- },
21
- find: async function (query, offset, limit, orderby, fields) {
22
- const data = await store.allAsync()
23
- const arr = Object.keys(data).map(function (id) {
24
- return data[id]
25
- })
26
- let matches = util.mongoSearch(arr, query)
27
- if (orderby) {
28
- matches = util.orderBy(matches, orderby)
29
- }
30
- if (typeof offset !== 'undefined' && typeof limit !== 'undefined') {
31
- matches = matches.slice(offset, offset + limit)
32
- } else if (typeof offset !== 'undefined') {
33
- matches = matches.slice(offset)
34
- } else if (typeof limit !== 'undefined') {
35
- matches = matches.slice(0, limit)
36
- }
37
- if (matches) { // prevent store from being modified
38
- matches = matches.map(function (m) {
39
- return util.clone(m)
40
- })
41
- } // prevent store from being modified
42
- if (fields) {
43
- matches = matches.map((doc) => util.mongoProject(doc, fields))
44
- }
45
- return matches
46
- },
47
- count: async function(...params) {
48
- return (await this.find(...params)).length
49
- },
50
- get: async function (id, fields) {
51
- try {
52
- let data = await store.getAsync(id)
53
- if (data) {
54
- data = util.clone(data) // prevent store from getting modified
55
- }
56
- if (fields) {
57
- data = util.mongoProject(data, fields)
58
- }
59
- return data
60
- } catch (err) {
61
- debug(collection + ' ' + id)
62
- throw new util.ApiError(404, 'document not found')
63
- }
64
- },
65
- exists: async function (id) {
66
- try {
67
- await store.getAsync(id)
68
- return true
69
- } catch (err) {
70
- return false
71
- }
72
- },
73
- create: async function (data) {
74
- data = util.sortObjectKeys(data)
75
- util.addIdIfMissing(data)
76
- const id = data._id
77
- const existing = await this.exists(id)
78
- if (existing) {
79
- throw new util.ApiError(409, 'document already exists')
80
- }
81
- await store.saveAsync(id, data)
82
- return id
83
- },
84
- update: async function (id, data) {
85
- data._id = data._id || id
86
- data = util.sortObjectKeys(data)
87
- await store.saveAsync(data._id, data)
88
- if (data._id !== id) {
89
- await store.delete(id)
90
- }
91
- return data
92
- },
93
- // eslint-disable-next-line no-unused-vars
94
- updateWithQuery: async function (query, update, options) {
95
- const data = await store.allAsync()
96
- const arr = Object.keys(data).map((id) => ({ _id: id, ...data[id]}) )
97
- const matches = util.mongoSearch(arr, query)
98
- const promises = matches.map((doc) => {
99
- util.mongoUpdate(doc, update)
100
- return store.saveAsync(doc._id, doc)
101
- })
102
- await Promise.all(promises)
103
- return {
104
- matchedCount: promises.length
105
- }
106
- },
107
- delete: async function (id) {
108
- await this.get(id) // to check if exists
109
- await store.delete(id)
110
- }
111
- }
112
- }
1
+ const Store = require('jfs')
2
+ const debug = require('debug')('expressa')
3
+ const { promisify } = require('util')
4
+ Store.prototype.allAsync = promisify(Store.prototype.all)
5
+ Store.prototype.getAsync = promisify(Store.prototype.get)
6
+ Store.prototype.saveAsync = promisify(Store.prototype.save)
7
+
8
+ const util = require('../util')
9
+
10
+ module.exports = function (settings, collection) {
11
+ const store = new Store((settings.file_storage_path || 'data') + '/' + collection, {
12
+ pretty: true,
13
+ saveId: '_id'
14
+ })
15
+
16
+ return {
17
+ init: function () {},
18
+ all: async function () {
19
+ return this.find({})
20
+ },
21
+ find: async function (query, offset, limit, orderby, fields) {
22
+ const data = await store.allAsync()
23
+ const arr = Object.keys(data).map(function (id) {
24
+ return data[id]
25
+ })
26
+ let matches = util.mongoSearch(arr, query)
27
+ if (orderby) {
28
+ matches = util.orderBy(matches, orderby)
29
+ }
30
+ if (typeof offset !== 'undefined' && typeof limit !== 'undefined') {
31
+ matches = matches.slice(offset, offset + limit)
32
+ } else if (typeof offset !== 'undefined') {
33
+ matches = matches.slice(offset)
34
+ } else if (typeof limit !== 'undefined') {
35
+ matches = matches.slice(0, limit)
36
+ }
37
+ if (matches) { // prevent store from being modified
38
+ matches = matches.map(function (m) {
39
+ return util.clone(m)
40
+ })
41
+ } // prevent store from being modified
42
+ if (fields) {
43
+ matches = matches.map((doc) => util.mongoProject(doc, fields))
44
+ }
45
+ return matches
46
+ },
47
+ count: async function(...params) {
48
+ return (await this.find(...params)).length
49
+ },
50
+ get: async function (id, fields) {
51
+ try {
52
+ let data = await store.getAsync(id)
53
+ if (data) {
54
+ data = util.clone(data) // prevent store from getting modified
55
+ }
56
+ if (fields) {
57
+ data = util.mongoProject(data, fields)
58
+ }
59
+ return data
60
+ } catch (err) {
61
+ debug(collection + ' ' + id)
62
+ throw new util.ApiError(404, 'document not found')
63
+ }
64
+ },
65
+ exists: async function (id) {
66
+ try {
67
+ await store.getAsync(id)
68
+ return true
69
+ } catch (err) {
70
+ return false
71
+ }
72
+ },
73
+ create: async function (data) {
74
+ data = util.sortObjectKeys(data)
75
+ util.addIdIfMissing(data)
76
+ const id = data._id
77
+ const existing = await this.exists(id)
78
+ if (existing) {
79
+ throw new util.ApiError(409, 'document already exists')
80
+ }
81
+ await store.saveAsync(id, data)
82
+ return id
83
+ },
84
+ update: async function (id, data) {
85
+ data._id = data._id || id
86
+ data = util.sortObjectKeys(data)
87
+ await store.saveAsync(data._id, data)
88
+ if (data._id !== id) {
89
+ await store.delete(id)
90
+ }
91
+ return data
92
+ },
93
+ // eslint-disable-next-line no-unused-vars
94
+ updateWithQuery: async function (query, update, options) {
95
+ const data = await store.allAsync()
96
+ const arr = Object.keys(data).map((id) => ({ _id: id, ...data[id]}) )
97
+ const matches = util.mongoSearch(arr, query)
98
+ const promises = matches.map((doc) => {
99
+ util.mongoUpdate(doc, update)
100
+ return store.saveAsync(doc._id, doc)
101
+ })
102
+ await Promise.all(promises)
103
+ return {
104
+ matchedCount: promises.length
105
+ }
106
+ },
107
+ delete: async function (id) {
108
+ await this.get(id) // to check if exists
109
+ await store.delete(id)
110
+ }
111
+ }
112
+ }
package/db/memory.js CHANGED
@@ -1,79 +1,79 @@
1
- /* eslint no-unused-vars: ["error", { "args": "none" }] */
2
- const util = require('../util')
3
-
4
- module.exports = function (settings, collection) {
5
- const store = {}
6
-
7
- return {
8
- type: 'memory',
9
- init: async function () {},
10
- all: async function () {
11
- return this.find({})
12
- },
13
- find: async function (query, offset, limit, orderby, fields) {
14
- const arr = Object.values(store)
15
- let matches = util.mongoSearch(arr, query)
16
- if (orderby) {
17
- matches = util.orderBy(matches, orderby)
18
- }
19
- if (typeof offset !== 'undefined' && typeof limit !== 'undefined') {
20
- matches = matches.slice(offset, offset + limit)
21
- } else if (typeof offset !== 'undefined') {
22
- matches = matches.slice(offset)
23
- } else if (typeof limit !== 'undefined') {
24
- matches = matches.slice(0, limit)
25
- }
26
- if (fields) {
27
- matches = matches.map((doc) => util.mongoProject(doc, fields))
28
- }
29
- return matches
30
- },
31
- count: async function(...params) {
32
- return (await this.find(...params)).length
33
- },
34
- get: async function (id, fields) {
35
- if (!store[id]) {
36
- throw new util.ApiError(404, 'document not found')
37
- }
38
- let doc = util.clone(store[id])
39
- if (fields) {
40
- doc = util.mongoProject(doc, fields)
41
- }
42
- return doc
43
- },
44
- create: async function (data) {
45
- util.addIdIfMissing(data)
46
- const id = data._id
47
- if (store[id]) {
48
- throw new util.ApiError(409, 'document already exists')
49
- }
50
- store[id] = data
51
- return id
52
- },
53
- update: async function (id, data) {
54
- data._id = data._id || id
55
- store[id] = data
56
- return data
57
- },
58
- // Designed to match Mongo
59
- // https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/
60
- updateWithQuery: async function (query, update, options) {
61
- const arr = Object.keys(store).map((id) => ({ _id: id, ...store[id]}) )
62
- const matches = util.mongoSearch(arr, query)
63
- matches.forEach((doc) => {
64
- util.mongoUpdate(doc, update)
65
- store[doc._id] = doc
66
- })
67
- return {
68
- matchedCount: matches.length
69
- }
70
- },
71
- delete: async function (id) {
72
- if (store[id]) {
73
- delete store[id]
74
- } else {
75
- throw new util.ApiError(404, 'document not found')
76
- }
77
- }
78
- }
79
- }
1
+ /* eslint no-unused-vars: ["error", { "args": "none" }] */
2
+ const util = require('../util')
3
+
4
+ module.exports = function (settings, collection) {
5
+ const store = {}
6
+
7
+ return {
8
+ type: 'memory',
9
+ init: async function () {},
10
+ all: async function () {
11
+ return this.find({})
12
+ },
13
+ find: async function (query, offset, limit, orderby, fields) {
14
+ const arr = Object.values(store)
15
+ let matches = util.mongoSearch(arr, query)
16
+ if (orderby) {
17
+ matches = util.orderBy(matches, orderby)
18
+ }
19
+ if (typeof offset !== 'undefined' && typeof limit !== 'undefined') {
20
+ matches = matches.slice(offset, offset + limit)
21
+ } else if (typeof offset !== 'undefined') {
22
+ matches = matches.slice(offset)
23
+ } else if (typeof limit !== 'undefined') {
24
+ matches = matches.slice(0, limit)
25
+ }
26
+ if (fields) {
27
+ matches = matches.map((doc) => util.mongoProject(doc, fields))
28
+ }
29
+ return matches
30
+ },
31
+ count: async function(...params) {
32
+ return (await this.find(...params)).length
33
+ },
34
+ get: async function (id, fields) {
35
+ if (!store[id]) {
36
+ throw new util.ApiError(404, 'document not found')
37
+ }
38
+ let doc = util.clone(store[id])
39
+ if (fields) {
40
+ doc = util.mongoProject(doc, fields)
41
+ }
42
+ return doc
43
+ },
44
+ create: async function (data) {
45
+ util.addIdIfMissing(data)
46
+ const id = data._id
47
+ if (store[id]) {
48
+ throw new util.ApiError(409, 'document already exists')
49
+ }
50
+ store[id] = data
51
+ return id
52
+ },
53
+ update: async function (id, data) {
54
+ data._id = data._id || id
55
+ store[id] = data
56
+ return data
57
+ },
58
+ // Designed to match Mongo
59
+ // https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/
60
+ updateWithQuery: async function (query, update, options) {
61
+ const arr = Object.keys(store).map((id) => ({ _id: id, ...store[id]}) )
62
+ const matches = util.mongoSearch(arr, query)
63
+ matches.forEach((doc) => {
64
+ util.mongoUpdate(doc, update)
65
+ store[doc._id] = doc
66
+ })
67
+ return {
68
+ matchedCount: matches.length
69
+ }
70
+ },
71
+ delete: async function (id) {
72
+ if (store[id]) {
73
+ delete store[id]
74
+ } else {
75
+ throw new util.ApiError(404, 'document not found')
76
+ }
77
+ }
78
+ }
79
+ }
package/db/mongo.js CHANGED
@@ -1,86 +1,86 @@
1
- const mongo = require('mongodb')
2
- const MongoClient = mongo.MongoClient
3
- const util = require('../util')
4
-
5
- module.exports = function (settings, collection) {
6
- return {
7
- getClient: async function () {
8
- const client = await MongoClient.connect(settings.mongodb_uri, { useNewUrlParser: true })
9
- const db = client.db(settings.mongodb_uri.split('/')[3])
10
- return db
11
- },
12
- init: function () {
13
- if (!settings.mongodb_uri) {
14
- console.error('{collection} uses mongo, but mongodb_url is undefined.')
15
- }
16
- },
17
- all: async function () {
18
- return this.find({})
19
- },
20
- find: async function (query, skip, limit, orderby, fields) {
21
- const db = await this.getClient()
22
- const cursor = db.collection(collection).find(query, { skip, limit, projection: fields, sort: orderby })
23
- const docs = await cursor.toArray()
24
- docs.forEach((doc) => {
25
- if (doc._id) {
26
- doc._id = doc._id.toString()
27
- }
28
- })
29
- return docs
30
- },
31
- count: async function(query, skip, limit) {
32
- const db = await this.getClient()
33
- const count = await db.collection(collection).count(query, { skip, limit })
34
- return count
35
- },
36
- get: async function (id, fields) {
37
- const db = await this.getClient()
38
- const doc = await db.collection(collection).findOne({ _id: id }, { projection: fields })
39
- if (doc) {
40
- doc._id = doc._id.toString()
41
- }
42
- if (!doc) {
43
- throw new util.ApiError(404, 'document not found')
44
- }
45
- return doc
46
- },
47
- create: async function (data) {
48
- util.addIdIfMissing(data)
49
-
50
- const db = await this.getClient()
51
- try {
52
- const doc = await db.collection(collection).insertOne(data)
53
- return doc.insertedId.toString()
54
- } catch (err) {
55
- if (err && err.message && err.message.includes('duplicate key error')) {
56
- throw new util.ApiError(409, 'document already exists')
57
- }
58
- }
59
- },
60
- update: async function (id, data) {
61
- data._id = id
62
- const db = await this.getClient()
63
- await db.collection(collection).replaceOne({
64
- _id: id
65
- }, data)
66
- // doc._id = doc._id.toString()
67
- return data
68
- },
69
- updateWithQuery: async function (query, update, options) {
70
- const db = await this.getClient()
71
- const res = await db.collection(collection).updateMany(query, update, options)
72
- return {
73
- matchedCount: res.matchedCount
74
- }
75
- },
76
- delete: async function (id) {
77
- const db = await this.getClient()
78
- const res = await db.collection(collection).deleteOne({
79
- _id: id
80
- })
81
- if (res.result.n !== 1) {
82
- throw new util.ApiError(404, 'document not found')
83
- }
84
- }
85
- }
86
- }
1
+ const mongo = require('mongodb')
2
+ const MongoClient = mongo.MongoClient
3
+ const util = require('../util')
4
+
5
+ module.exports = function (settings, collection) {
6
+ return {
7
+ getClient: async function () {
8
+ const client = await MongoClient.connect(settings.mongodb_uri, { useNewUrlParser: true })
9
+ const db = client.db(settings.mongodb_uri.split('/')[3])
10
+ return db
11
+ },
12
+ init: function () {
13
+ if (!settings.mongodb_uri) {
14
+ console.error('{collection} uses mongo, but mongodb_url is undefined.')
15
+ }
16
+ },
17
+ all: async function () {
18
+ return this.find({})
19
+ },
20
+ find: async function (query, skip, limit, orderby, fields) {
21
+ const db = await this.getClient()
22
+ const cursor = db.collection(collection).find(query, { skip, limit, projection: fields, sort: orderby })
23
+ const docs = await cursor.toArray()
24
+ docs.forEach((doc) => {
25
+ if (doc._id) {
26
+ doc._id = doc._id.toString()
27
+ }
28
+ })
29
+ return docs
30
+ },
31
+ count: async function(query, skip, limit) {
32
+ const db = await this.getClient()
33
+ const count = await db.collection(collection).count(query, { skip, limit })
34
+ return count
35
+ },
36
+ get: async function (id, fields) {
37
+ const db = await this.getClient()
38
+ const doc = await db.collection(collection).findOne({ _id: id }, { projection: fields })
39
+ if (doc) {
40
+ doc._id = doc._id.toString()
41
+ }
42
+ if (!doc) {
43
+ throw new util.ApiError(404, 'document not found')
44
+ }
45
+ return doc
46
+ },
47
+ create: async function (data) {
48
+ util.addIdIfMissing(data)
49
+
50
+ const db = await this.getClient()
51
+ try {
52
+ const doc = await db.collection(collection).insertOne(data)
53
+ return doc.insertedId.toString()
54
+ } catch (err) {
55
+ if (err && err.message && err.message.includes('duplicate key error')) {
56
+ throw new util.ApiError(409, 'document already exists')
57
+ }
58
+ }
59
+ },
60
+ update: async function (id, data) {
61
+ data._id = id
62
+ const db = await this.getClient()
63
+ await db.collection(collection).replaceOne({
64
+ _id: id
65
+ }, data)
66
+ // doc._id = doc._id.toString()
67
+ return data
68
+ },
69
+ updateWithQuery: async function (query, update, options) {
70
+ const db = await this.getClient()
71
+ const res = await db.collection(collection).updateMany(query, update, options)
72
+ return {
73
+ matchedCount: res.matchedCount
74
+ }
75
+ },
76
+ delete: async function (id) {
77
+ const db = await this.getClient()
78
+ const res = await db.collection(collection).deleteOne({
79
+ _id: id
80
+ })
81
+ if (res.result.n !== 1) {
82
+ throw new util.ApiError(404, 'document not found')
83
+ }
84
+ }
85
+ }
86
+ }