expressa 2.0.21 → 2.0.22
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.
- package/.circleci/config.yml +21 -21
- package/.eslintrc.json +29 -29
- package/.vscode/launch.json +19 -0
- package/LICENSE +21 -21
- package/README.md +137 -137
- package/auth/index.js +76 -76
- package/auth/jwt.js +31 -31
- package/controllers/collections.js +260 -260
- package/controllers/install.js +105 -105
- package/controllers/status.js +43 -43
- package/controllers/users.js +52 -52
- package/cypress/fixtures/example.json +4 -4
- package/cypress/integration/0_install_spec.js +8 -8
- package/cypress/integration/custom_collections.js +30 -30
- package/cypress/integration/home.js +9 -9
- package/cypress/integration/settings.js +34 -34
- package/cypress/integration/users.js +61 -61
- package/cypress/plugins/index.js +17 -17
- package/cypress/support/commands.js +69 -69
- package/cypress/support/index.js +20 -20
- package/cypress/support/util.js +10 -10
- package/cypress.config.js +18 -18
- package/cypress.json +4 -4
- package/db/cached.js +44 -40
- package/db/file.js +131 -112
- package/db/memory.js +92 -79
- package/db/mongo.js +93 -86
- package/db/postgres.js +100 -93
- package/doc/authentication.md +38 -38
- package/doc/automatic-fields.md +12 -12
- package/doc/blogexample.md +16 -16
- package/doc/custom-endpoints.md +20 -20
- package/doc/database.md +23 -23
- package/doc/development.md +33 -33
- package/doc/listeners.md +103 -103
- package/doc/modules.md +8 -8
- package/doc/permissions.md +14 -14
- package/doc/relationships.md +65 -65
- package/doc/testing.md +47 -47
- package/doc/uploading-files.md +53 -53
- package/index.js +297 -297
- package/listeners.js +65 -65
- package/listeners_collection_permissions.js +29 -29
- package/listeners_users.js +96 -96
- package/listeners_validation.js +43 -43
- package/middleware/logging.js +30 -30
- package/middleware/permissions.js +41 -41
- package/modules/access_keys/access_keys.js +32 -32
- package/modules/admin/.babelrc +19 -19
- package/modules/admin/.editorconfig +14 -14
- package/modules/admin/.eslintignore +5 -5
- package/modules/admin/.eslintrc.js +197 -197
- package/modules/admin/.postcssrc.js +10 -10
- package/modules/admin/.travis.yml +5 -5
- package/modules/admin/LICENSE +21 -21
- package/modules/admin/README.md +88 -88
- package/modules/admin/build/build.js +46 -46
- package/modules/admin/build/check-versions.js +64 -64
- package/modules/admin/build/utils.js +109 -109
- package/modules/admin/build/vue-loader.conf.js +5 -5
- package/modules/admin/build/webpack.base.conf.js +112 -112
- package/modules/admin/build/webpack.dev.conf.js +95 -95
- package/modules/admin/build/webpack.prod.conf.js +112 -112
- package/modules/admin/config/dev.env.js +8 -8
- package/modules/admin/config/index.js +86 -86
- package/modules/admin/config/prod.env.js +5 -5
- package/modules/admin/dist/css/136.1055b646.css +69 -0
- package/modules/admin/dist/css/136.1055b646.css.gz +0 -0
- package/modules/admin/dist/css/{430.8c9b0482.css → 165.e83d8cfe.css} +4 -4
- package/modules/admin/dist/css/165.e83d8cfe.css.gz +0 -0
- package/modules/admin/dist/css/220.e946bda7.css.gz +0 -0
- package/modules/admin/dist/css/{197.7a90435e.css → 236.e66ce8d8.css} +4 -4
- package/modules/admin/dist/css/236.e66ce8d8.css.gz +0 -0
- package/modules/admin/dist/css/338.1fd9d57c.css.gz +0 -0
- package/modules/admin/dist/css/{566.7a90435e.css → 566.e66ce8d8.css} +4 -4
- package/modules/admin/dist/css/566.e66ce8d8.css.gz +0 -0
- package/modules/admin/dist/css/76.46fe6799.css +66 -0
- package/modules/admin/dist/css/76.46fe6799.css.gz +0 -0
- package/modules/admin/dist/css/807.f450521e.css +1 -0
- package/modules/admin/dist/css/807.f450521e.css.gz +0 -0
- package/modules/admin/dist/css/{750.4086915d.css.gz → 913.4086915d.css.gz} +0 -0
- package/modules/admin/dist/css/{app.eba5f5e2.css → app.1c3232a3.css} +25 -25
- package/modules/admin/dist/css/app.1c3232a3.css.gz +0 -0
- package/modules/admin/dist/index.html +1 -1
- package/modules/admin/dist/static/js/115.108d0dd5.js +1 -0
- package/modules/admin/dist/static/js/115.108d0dd5.js.gz +0 -0
- package/modules/admin/dist/static/js/136.1f9f4cb0.js +1 -0
- package/modules/admin/dist/static/js/136.1f9f4cb0.js.gz +0 -0
- package/modules/admin/dist/static/js/165.b3d51941.js +1 -0
- package/modules/admin/dist/static/js/165.b3d51941.js.gz +0 -0
- package/modules/admin/dist/static/js/220.02b2cd49.js +1 -0
- package/modules/admin/dist/static/js/220.02b2cd49.js.gz +0 -0
- package/modules/admin/dist/static/js/236.98c79868.js +1 -0
- package/modules/admin/dist/static/js/236.98c79868.js.gz +0 -0
- package/modules/admin/dist/static/js/338.4ba49501.js +1 -0
- package/modules/admin/dist/static/js/338.4ba49501.js.gz +0 -0
- package/modules/admin/dist/static/js/381.a05421de.js +1 -0
- package/modules/admin/dist/static/js/381.a05421de.js.gz +0 -0
- package/modules/admin/dist/static/js/412.0914ff23.js +1 -0
- package/modules/admin/dist/static/js/412.0914ff23.js.gz +0 -0
- package/modules/admin/dist/static/js/533.507df4cb.js +1 -0
- package/modules/admin/dist/static/js/533.507df4cb.js.gz +0 -0
- package/modules/admin/dist/static/js/556.d7586b89.js +1 -0
- package/modules/admin/dist/static/js/556.d7586b89.js.gz +0 -0
- package/modules/admin/dist/static/js/76.811d0e96.js +1 -0
- package/modules/admin/dist/static/js/76.811d0e96.js.gz +0 -0
- package/modules/admin/dist/static/js/807.8b7455a7.js +1 -0
- package/modules/admin/dist/static/js/807.8b7455a7.js.gz +0 -0
- package/modules/admin/dist/static/js/913.8b376386.js +1 -0
- package/modules/admin/dist/static/js/913.8b376386.js.gz +0 -0
- package/modules/admin/dist/static/js/app.834abee4.js +2 -0
- package/modules/admin/dist/static/js/{app.083328f8.js.LICENSE.txt → app.834abee4.js.LICENSE.txt} +3 -3
- package/modules/admin/dist/static/js/app.834abee4.js.LICENSE.txt.gz +0 -0
- package/modules/admin/dist/static/js/app.834abee4.js.gz +0 -0
- package/modules/admin/index.html +16 -16
- package/modules/admin/package.json +102 -101
- package/modules/admin/src/App.vue +11 -11
- package/modules/admin/src/api/login.js +26 -26
- package/modules/admin/src/api/table.js +9 -9
- package/modules/admin/src/components/Breadcrumb/index.vue +79 -79
- package/modules/admin/src/components/Hamburger/index.vue +62 -62
- package/modules/admin/src/components/JSONEditor.vue +206 -180
- package/modules/admin/src/components/SvgIcon/index.vue +43 -43
- package/modules/admin/src/icons/index.js +9 -9
- package/modules/admin/src/icons/svgo.yml +22 -22
- package/modules/admin/src/main.js +42 -42
- package/modules/admin/src/permission.js +49 -49
- package/modules/admin/src/router/index.js +200 -200
- package/modules/admin/src/store/getters.js +11 -11
- package/modules/admin/src/store/index.js +17 -17
- package/modules/admin/src/store/modules/app.js +43 -43
- package/modules/admin/src/store/modules/user.js +104 -104
- package/modules/admin/src/styles/element-ui.scss +29 -29
- package/modules/admin/src/styles/index.scss +78 -78
- package/modules/admin/src/styles/mixin.scss +27 -27
- package/modules/admin/src/styles/sidebar.scss +133 -133
- package/modules/admin/src/styles/transition.scss +46 -46
- package/modules/admin/src/styles/variables.scss +4 -4
- package/modules/admin/src/utils/auth.js +15 -15
- package/modules/admin/src/utils/index.js +74 -74
- package/modules/admin/src/utils/request.js +47 -47
- package/modules/admin/src/utils/validate.js +31 -31
- package/modules/admin/src/views/404.vue +235 -235
- package/modules/admin/src/views/Dev.vue +33 -33
- package/modules/admin/src/views/EditDocument.vue +121 -121
- package/modules/admin/src/views/Endpoints.vue +279 -279
- package/modules/admin/src/views/Home.vue +84 -84
- package/modules/admin/src/views/Install.vue +79 -79
- package/modules/admin/src/views/ListDocuments.vue +72 -72
- package/modules/admin/src/views/ListDocuments2.vue +467 -467
- package/modules/admin/src/views/ManageListeners.vue +67 -67
- package/modules/admin/src/views/ManageMiddleware.vue +43 -43
- package/modules/admin/src/views/ManagePermissions.vue +75 -75
- package/modules/admin/src/views/ViewRequest.vue +77 -77
- package/modules/admin/src/views/form/index.vue +91 -91
- package/modules/admin/src/views/layout/Layout.vue +69 -69
- package/modules/admin/src/views/layout/components/AppMain.vue +41 -41
- package/modules/admin/src/views/layout/components/Navbar.vue +97 -97
- package/modules/admin/src/views/layout/components/Sidebar/Item.vue +29 -29
- package/modules/admin/src/views/layout/components/Sidebar/Link.vue +39 -39
- package/modules/admin/src/views/layout/components/Sidebar/SidebarItem.vue +103 -103
- package/modules/admin/src/views/layout/components/Sidebar/index.vue +62 -62
- package/modules/admin/src/views/layout/components/index.js +3 -3
- package/modules/admin/src/views/layout/mixin/ResizeHandler.js +41 -41
- package/modules/admin/src/views/login/index.vue +195 -195
- package/modules/admin/src/views/tree/index.vue +77 -77
- package/modules/collections/collections.js +39 -39
- package/modules/core/core.js +197 -197
- package/modules/logging/logging.js +88 -88
- package/modules/permissions/permissions.js +106 -106
- package/package.json +59 -59
- package/scripts/expressa +12 -12
- package/scripts/run_cypress_tests.sh +35 -35
- package/scripts/run_db_tests.sh +8 -8
- package/test/0-install.js +96 -96
- package/test/collections.js +431 -431
- package/test/collections.querying.js +288 -288
- package/test/db.js +258 -258
- package/test/db.strings.js +73 -73
- package/test/db.updating.js +186 -144
- package/test/logging.js +29 -29
- package/test/test.js +93 -93
- package/test/testserver.js +30 -30
- package/test/testutils.js +136 -136
- package/test/users.js +425 -425
- package/util.js +522 -522
- package/modules/admin/dist/css/197.7a90435e.css.gz +0 -0
- package/modules/admin/dist/css/430.8c9b0482.css.gz +0 -0
- package/modules/admin/dist/css/451.c6646d20.css +0 -1
- package/modules/admin/dist/css/451.c6646d20.css.gz +0 -0
- package/modules/admin/dist/css/566.7a90435e.css.gz +0 -0
- package/modules/admin/dist/css/569.f7d5c7d5.css +0 -37
- package/modules/admin/dist/css/569.f7d5c7d5.css.gz +0 -0
- package/modules/admin/dist/css/572.74d8e965.css +0 -34
- package/modules/admin/dist/css/572.74d8e965.css.gz +0 -0
- package/modules/admin/dist/css/651.e946bda7.css.gz +0 -0
- package/modules/admin/dist/css/950.1fd9d57c.css.gz +0 -0
- package/modules/admin/dist/css/app.eba5f5e2.css.gz +0 -0
- package/modules/admin/dist/static/js/197.e511d91e.js +0 -1
- package/modules/admin/dist/static/js/197.e511d91e.js.gz +0 -0
- package/modules/admin/dist/static/js/430.b3941f30.js +0 -1
- package/modules/admin/dist/static/js/430.b3941f30.js.gz +0 -0
- package/modules/admin/dist/static/js/451.645974a8.js +0 -1
- package/modules/admin/dist/static/js/451.645974a8.js.gz +0 -0
- package/modules/admin/dist/static/js/460.962d5bc0.js +0 -1
- package/modules/admin/dist/static/js/460.962d5bc0.js.gz +0 -0
- package/modules/admin/dist/static/js/550.f27feb23.js +0 -1
- package/modules/admin/dist/static/js/550.f27feb23.js.gz +0 -0
- package/modules/admin/dist/static/js/556.1e08866a.js +0 -1
- package/modules/admin/dist/static/js/556.1e08866a.js.gz +0 -0
- package/modules/admin/dist/static/js/569.0fecfbee.js +0 -1
- package/modules/admin/dist/static/js/569.0fecfbee.js.gz +0 -0
- package/modules/admin/dist/static/js/572.13392e1d.js +0 -1
- package/modules/admin/dist/static/js/572.13392e1d.js.gz +0 -0
- package/modules/admin/dist/static/js/603.7b34a650.js +0 -1
- package/modules/admin/dist/static/js/603.7b34a650.js.gz +0 -0
- package/modules/admin/dist/static/js/651.564b24b6.js +0 -1
- package/modules/admin/dist/static/js/651.564b24b6.js.gz +0 -0
- package/modules/admin/dist/static/js/653.02ec1098.js +0 -1
- package/modules/admin/dist/static/js/653.02ec1098.js.gz +0 -0
- package/modules/admin/dist/static/js/750.50c950da.js +0 -1
- package/modules/admin/dist/static/js/750.50c950da.js.gz +0 -0
- package/modules/admin/dist/static/js/950.d4ff0a18.js +0 -1
- package/modules/admin/dist/static/js/950.d4ff0a18.js.gz +0 -0
- package/modules/admin/dist/static/js/app.083328f8.js +0 -2
- package/modules/admin/dist/static/js/app.083328f8.js.LICENSE.txt.gz +0 -0
- package/modules/admin/dist/static/js/app.083328f8.js.gz +0 -0
- /package/modules/admin/dist/css/{651.e946bda7.css → 220.e946bda7.css} +0 -0
- /package/modules/admin/dist/css/{950.1fd9d57c.css → 338.1fd9d57c.css} +0 -0
- /package/modules/admin/dist/css/{750.4086915d.css → 913.4086915d.css} +0 -0
package/db/file.js
CHANGED
|
@@ -1,112 +1,131 @@
|
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
+
updateWithQuerySingle: async function (id, update, options) {
|
|
108
|
+
try {
|
|
109
|
+
const doc = await store.getAsync(id)
|
|
110
|
+
if (!doc) {
|
|
111
|
+
return {
|
|
112
|
+
matchedCount: 0
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
util.mongoUpdate(doc, update)
|
|
116
|
+
await store.saveAsync(id, doc)
|
|
117
|
+
return {
|
|
118
|
+
matchedCount: 1
|
|
119
|
+
}
|
|
120
|
+
} catch (err) {
|
|
121
|
+
return {
|
|
122
|
+
matchedCount: 0
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
delete: async function (id) {
|
|
127
|
+
await this.get(id) // to check if exists
|
|
128
|
+
await store.delete(id)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
package/db/memory.js
CHANGED
|
@@ -1,79 +1,92 @@
|
|
|
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
|
-
|
|
72
|
-
if (store[id]) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
+
updateWithQuerySingle: async function (id, update, options) {
|
|
72
|
+
if (!store[id]) {
|
|
73
|
+
return {
|
|
74
|
+
matchedCount: 0
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const doc = { _id: id, ...store[id] }
|
|
78
|
+
util.mongoUpdate(doc, update)
|
|
79
|
+
store[id] = doc
|
|
80
|
+
return {
|
|
81
|
+
matchedCount: 1
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
delete: async function (id) {
|
|
85
|
+
if (store[id]) {
|
|
86
|
+
delete store[id]
|
|
87
|
+
} else {
|
|
88
|
+
throw new util.ApiError(404, 'document not found')
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
package/db/mongo.js
CHANGED
|
@@ -1,86 +1,93 @@
|
|
|
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
|
-
|
|
77
|
-
const db = await this.getClient()
|
|
78
|
-
const res = await db.collection(collection).
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
+
updateWithQuerySingle: async function (id, update, options) {
|
|
77
|
+
const db = await this.getClient()
|
|
78
|
+
const res = await db.collection(collection).updateOne({ _id: id }, update, options)
|
|
79
|
+
return {
|
|
80
|
+
matchedCount: res.matchedCount
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
delete: async function (id) {
|
|
84
|
+
const db = await this.getClient()
|
|
85
|
+
const res = await db.collection(collection).deleteOne({
|
|
86
|
+
_id: id
|
|
87
|
+
})
|
|
88
|
+
if (res.result.n !== 1) {
|
|
89
|
+
throw new util.ApiError(404, 'document not found')
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|