@budibase/server 0.9.140-alpha.1 → 0.9.140-alpha.5
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/builder/assets/{index.e8745f5e.js → index.80d850d1.js} +35 -35
- package/builder/assets/{vendor.d39b3c1e.js → vendor.820de34b.js} +10 -2
- package/builder/index.html +2 -2
- package/coverage/clover.xml +798 -530
- package/coverage/coverage-final.json +19 -16
- package/coverage/lcov-report/api/controllers/analytics.js.html +4 -4
- package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/controllers/application.js.html +1 -1
- package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
- package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
- package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
- package/coverage/lcov-report/api/controllers/component.js.html +1 -1
- package/coverage/lcov-report/api/controllers/datasource.js.html +3 -3
- package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
- package/coverage/lcov-report/api/controllers/hosting.js.html +1 -1
- package/coverage/lcov-report/api/controllers/index.html +5 -5
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
- package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
- package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
- package/coverage/lcov-report/api/controllers/query.js.html +1 -1
- package/coverage/lcov-report/api/controllers/role.js.html +1 -1
- package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/index.html +34 -19
- package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/internal.js.html +242 -47
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1244 -0
- package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
- package/coverage/lcov-report/api/controllers/script.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.js.html +2 -2
- package/coverage/lcov-report/api/controllers/table/utils.js.html +31 -19
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.html +32 -17
- package/coverage/lcov-report/api/controllers/view/index.js.html +84 -186
- package/coverage/lcov-report/api/controllers/view/utils.js.html +407 -0
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
- package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/routes/application.js.html +1 -1
- package/coverage/lcov-report/api/routes/auth.js.html +1 -1
- package/coverage/lcov-report/api/routes/automation.js.html +1 -1
- package/coverage/lcov-report/api/routes/backup.js.html +1 -1
- package/coverage/lcov-report/api/routes/component.js.html +1 -1
- package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
- package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
- package/coverage/lcov-report/api/routes/dev.js.html +1 -1
- package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
- package/coverage/lcov-report/api/routes/index.html +1 -1
- package/coverage/lcov-report/api/routes/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/integration.js.html +1 -1
- package/coverage/lcov-report/api/routes/layout.js.html +1 -1
- package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
- package/coverage/lcov-report/api/routes/permission.js.html +1 -1
- package/coverage/lcov-report/api/routes/query.js.html +1 -1
- package/coverage/lcov-report/api/routes/role.js.html +1 -1
- package/coverage/lcov-report/api/routes/routing.js.html +1 -1
- package/coverage/lcov-report/api/routes/row.js.html +1 -1
- package/coverage/lcov-report/api/routes/screen.js.html +1 -1
- package/coverage/lcov-report/api/routes/script.js.html +1 -1
- package/coverage/lcov-report/api/routes/static.js.html +1 -1
- package/coverage/lcov-report/api/routes/table.js.html +1 -1
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +1 -1
- package/coverage/lcov-report/api/routes/view.js.html +1 -1
- package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/actions.js.html +1 -1
- package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
- package/coverage/lcov-report/automations/bullboard.js.html +1 -1
- package/coverage/lcov-report/automations/index.html +1 -1
- package/coverage/lcov-report/automations/index.js.html +1 -1
- package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
- package/coverage/lcov-report/automations/steps/createRow.js.html +10 -19
- package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
- package/coverage/lcov-report/automations/steps/deleteRow.js.html +14 -20
- package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +31 -31
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
- package/coverage/lcov-report/automations/steps/queryRows.js.html +18 -27
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
- package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
- package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
- package/coverage/lcov-report/automations/steps/updateRow.js.html +12 -21
- package/coverage/lcov-report/automations/steps/utils.js.html +23 -23
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/thread.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/triggers.js.html +1 -1
- package/coverage/lcov-report/automations/utils.js.html +1 -1
- package/coverage/lcov-report/constants/index.html +1 -1
- package/coverage/lcov-report/constants/index.js.html +1 -1
- package/coverage/lcov-report/constants/layouts.js.html +1 -1
- package/coverage/lcov-report/constants/screens.js.html +1 -1
- package/coverage/lcov-report/db/client.js.html +1 -1
- package/coverage/lcov-report/db/inMemoryView.js.html +224 -0
- package/coverage/lcov-report/db/index.html +34 -19
- package/coverage/lcov-report/db/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +4 -4
- package/coverage/lcov-report/db/linkedRows/index.html +14 -14
- package/coverage/lcov-report/db/linkedRows/index.js.html +18 -9
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
- package/coverage/lcov-report/db/newid.js.html +1 -1
- package/coverage/lcov-report/db/utils.js.html +37 -10
- package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
- package/coverage/lcov-report/events/index.html +1 -1
- package/coverage/lcov-report/events/index.js.html +1 -1
- package/coverage/lcov-report/events/utils.js.html +1 -1
- package/coverage/lcov-report/index.html +68 -68
- package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
- package/coverage/lcov-report/integrations/tests/index.html +1 -1
- package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
- package/coverage/lcov-report/middleware/authorized.js.html +1 -1
- package/coverage/lcov-report/middleware/builder.js.html +1 -1
- package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
- package/coverage/lcov-report/middleware/index.html +1 -1
- package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
- package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
- package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
- package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
- package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
- package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
- package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
- package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
- package/coverage/lcov-report/utilities/global.js.html +1 -1
- package/coverage/lcov-report/utilities/index.html +1 -1
- package/coverage/lcov-report/utilities/index.js.html +1 -1
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
- package/coverage/lcov-report/utilities/queue/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.html +15 -15
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +58 -13
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
- package/coverage/lcov-report/utilities/security.js.html +2 -2
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +1 -1
- package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
- package/coverage/lcov.info +1405 -886
- package/dist/api/controllers/analytics.js +1 -1
- package/dist/api/controllers/datasource.js +2 -2
- package/dist/api/controllers/row/ExternalRequest.js +4 -0
- package/dist/api/controllers/row/internal.js +97 -23
- package/dist/api/controllers/table/index.js +1 -1
- package/dist/api/controllers/table/utils.js +13 -11
- package/dist/api/controllers/view/index.js +74 -96
- package/dist/api/controllers/view/utils.js +102 -0
- package/dist/automations/steps/createRow.js +5 -8
- package/dist/automations/steps/deleteRow.js +7 -10
- package/dist/automations/steps/queryRows.js +11 -14
- package/dist/automations/steps/updateRow.js +4 -7
- package/dist/db/inMemoryView.js +51 -0
- package/dist/db/linkedRows/index.js +5 -2
- package/dist/db/utils.js +7 -0
- package/dist/environment.js +7 -1
- package/dist/integrations/mysql.js +2 -13
- package/dist/integrations/postgres.js +8 -14
- package/dist/integrations/utils.js +19 -1
- package/dist/package.json +10 -12
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/rowProcessor/index.js +10 -5
- package/package.json +11 -13
- package/scripts/integrations/service-vehicles/docker-compose.yml +28 -0
- package/scripts/integrations/service-vehicles/init.sql +52 -0
- package/scripts/integrations/service-vehicles/reset.sh +3 -0
- package/src/api/controllers/analytics.js +1 -1
- package/src/api/controllers/datasource.js +2 -2
- package/src/api/controllers/row/ExternalRequest.ts +5 -1
- package/src/api/controllers/row/internal.js +88 -23
- package/src/api/controllers/table/index.js +1 -1
- package/src/api/controllers/table/utils.js +16 -12
- package/src/api/controllers/view/index.js +82 -116
- package/src/api/controllers/view/utils.js +109 -0
- package/src/api/routes/tests/view.spec.js +1 -1
- package/src/automations/steps/createRow.js +5 -8
- package/src/automations/steps/deleteRow.js +8 -10
- package/src/automations/steps/queryRows.js +11 -14
- package/src/automations/steps/updateRow.js +7 -10
- package/src/db/inMemoryView.js +48 -0
- package/src/db/linkedRows/index.js +5 -2
- package/src/db/utils.js +9 -0
- package/src/environment.js +8 -1
- package/src/integrations/mysql.ts +2 -13
- package/src/integrations/postgres.ts +9 -16
- package/src/integrations/utils.ts +18 -0
- package/src/utilities/rowProcessor/index.js +20 -5
|
@@ -2,127 +2,93 @@ const CouchDB = require("../../../db")
|
|
|
2
2
|
const viewTemplate = require("./viewBuilder")
|
|
3
3
|
const { apiFileReturn } = require("../../../utilities/fileSystem")
|
|
4
4
|
const exporters = require("./exporters")
|
|
5
|
+
const { saveView, getView, getViews, deleteView } = require("./utils")
|
|
5
6
|
const { fetchView } = require("../row")
|
|
6
|
-
const { ViewNames } = require("../../../db/utils")
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const response = []
|
|
13
|
-
|
|
14
|
-
for (let name of Object.keys(designDoc.views)) {
|
|
15
|
-
// Only return custom views, not built ins
|
|
16
|
-
if (Object.values(ViewNames).indexOf(name) !== -1) {
|
|
17
|
-
continue
|
|
18
|
-
}
|
|
19
|
-
response.push({
|
|
20
|
-
name,
|
|
21
|
-
...designDoc.views[name],
|
|
22
|
-
})
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
ctx.body = response
|
|
26
|
-
},
|
|
27
|
-
save: async ctx => {
|
|
28
|
-
const db = new CouchDB(ctx.appId)
|
|
29
|
-
const { originalName, ...viewToSave } = ctx.request.body
|
|
30
|
-
const designDoc = await db.get("_design/database")
|
|
31
|
-
const view = viewTemplate(viewToSave)
|
|
32
|
-
|
|
33
|
-
if (!viewToSave.name) {
|
|
34
|
-
ctx.throw(400, "Cannot create view without a name")
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
designDoc.views = {
|
|
38
|
-
...designDoc.views,
|
|
39
|
-
[viewToSave.name]: view,
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// view has been renamed
|
|
43
|
-
if (originalName) {
|
|
44
|
-
delete designDoc.views[originalName]
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
await db.put(designDoc)
|
|
48
|
-
|
|
49
|
-
// add views to table document
|
|
50
|
-
const table = await db.get(ctx.request.body.tableId)
|
|
51
|
-
if (!table.views) table.views = {}
|
|
52
|
-
if (!view.meta.schema) {
|
|
53
|
-
view.meta.schema = table.schema
|
|
54
|
-
}
|
|
55
|
-
table.views[viewToSave.name] = view.meta
|
|
56
|
-
|
|
57
|
-
if (originalName) {
|
|
58
|
-
delete table.views[originalName]
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
await db.put(table)
|
|
62
|
-
|
|
63
|
-
ctx.body = {
|
|
64
|
-
...table.views[viewToSave.name],
|
|
65
|
-
name: viewToSave.name,
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
destroy: async ctx => {
|
|
69
|
-
const db = new CouchDB(ctx.appId)
|
|
70
|
-
const designDoc = await db.get("_design/database")
|
|
71
|
-
const viewName = decodeURI(ctx.params.viewName)
|
|
72
|
-
const view = designDoc.views[viewName]
|
|
73
|
-
delete designDoc.views[viewName]
|
|
74
|
-
|
|
75
|
-
await db.put(designDoc)
|
|
76
|
-
|
|
77
|
-
const table = await db.get(view.meta.tableId)
|
|
78
|
-
delete table.views[viewName]
|
|
79
|
-
await db.put(table)
|
|
80
|
-
|
|
81
|
-
ctx.body = view
|
|
82
|
-
},
|
|
83
|
-
exportView: async ctx => {
|
|
84
|
-
const db = new CouchDB(ctx.appId)
|
|
85
|
-
const designDoc = await db.get("_design/database")
|
|
86
|
-
const viewName = decodeURI(ctx.query.view)
|
|
8
|
+
exports.fetch = async ctx => {
|
|
9
|
+
const db = new CouchDB(ctx.appId)
|
|
10
|
+
ctx.body = await getViews(db)
|
|
11
|
+
}
|
|
87
12
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
13
|
+
exports.save = async ctx => {
|
|
14
|
+
const db = new CouchDB(ctx.appId)
|
|
15
|
+
const { originalName, ...viewToSave } = ctx.request.body
|
|
16
|
+
const view = viewTemplate(viewToSave)
|
|
17
|
+
|
|
18
|
+
if (!viewToSave.name) {
|
|
19
|
+
ctx.throw(400, "Cannot create view without a name")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
await saveView(db, originalName, viewToSave.name, view)
|
|
23
|
+
|
|
24
|
+
// add views to table document
|
|
25
|
+
const table = await db.get(ctx.request.body.tableId)
|
|
26
|
+
if (!table.views) table.views = {}
|
|
27
|
+
if (!view.meta.schema) {
|
|
28
|
+
view.meta.schema = table.schema
|
|
29
|
+
}
|
|
30
|
+
table.views[viewToSave.name] = view.meta
|
|
31
|
+
if (originalName) {
|
|
32
|
+
delete table.views[originalName]
|
|
33
|
+
}
|
|
34
|
+
await db.put(table)
|
|
35
|
+
|
|
36
|
+
ctx.body = {
|
|
37
|
+
...table.views[viewToSave.name],
|
|
38
|
+
name: viewToSave.name,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
93
41
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
field: view.meta.field,
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
// table all_ view
|
|
105
|
-
/* istanbul ignore next */
|
|
106
|
-
ctx.params.viewName = viewName
|
|
107
|
-
}
|
|
42
|
+
exports.destroy = async ctx => {
|
|
43
|
+
const db = new CouchDB(ctx.appId)
|
|
44
|
+
const viewName = decodeURI(ctx.params.viewName)
|
|
45
|
+
const view = await deleteView(db, viewName)
|
|
46
|
+
const table = await db.get(view.meta.tableId)
|
|
47
|
+
delete table.views[viewName]
|
|
48
|
+
await db.put(table)
|
|
108
49
|
|
|
109
|
-
|
|
50
|
+
ctx.body = view
|
|
51
|
+
}
|
|
110
52
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
53
|
+
exports.exportView = async ctx => {
|
|
54
|
+
const db = new CouchDB(ctx.appId)
|
|
55
|
+
const viewName = decodeURI(ctx.query.view)
|
|
56
|
+
const view = await getView(db, viewName)
|
|
57
|
+
|
|
58
|
+
const format = ctx.query.format
|
|
59
|
+
if (!format) {
|
|
60
|
+
ctx.throw(400, "Format must be specified, either csv or json")
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (view) {
|
|
64
|
+
ctx.params.viewName = viewName
|
|
65
|
+
// Fetch view rows
|
|
66
|
+
ctx.query = {
|
|
67
|
+
group: view.meta.groupBy,
|
|
68
|
+
calculation: view.meta.calculation,
|
|
69
|
+
stats: !!view.meta.field,
|
|
70
|
+
field: view.meta.field,
|
|
116
71
|
}
|
|
117
|
-
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
72
|
+
} else {
|
|
73
|
+
// table all_ view
|
|
74
|
+
/* istanbul ignore next */
|
|
75
|
+
ctx.params.viewName = viewName
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
await fetchView(ctx)
|
|
79
|
+
|
|
80
|
+
let schema = view && view.meta && view.meta.schema
|
|
81
|
+
if (!schema) {
|
|
82
|
+
const tableId = ctx.params.tableId || view.meta.tableId
|
|
83
|
+
const table = await db.get(tableId)
|
|
84
|
+
schema = table.schema
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Export part
|
|
88
|
+
let headers = Object.keys(schema)
|
|
89
|
+
const exporter = exporters[format]
|
|
90
|
+
const filename = `${viewName}.${format}`
|
|
91
|
+
// send down the file
|
|
92
|
+
ctx.attachment(filename)
|
|
93
|
+
ctx.body = apiFileReturn(exporter(headers, ctx.body))
|
|
126
94
|
}
|
|
127
|
-
|
|
128
|
-
module.exports = controller
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const {
|
|
2
|
+
ViewNames,
|
|
3
|
+
generateMemoryViewID,
|
|
4
|
+
getMemoryViewParams,
|
|
5
|
+
} = require("../../../db/utils")
|
|
6
|
+
const env = require("../../../environment")
|
|
7
|
+
|
|
8
|
+
exports.getView = async (db, viewName) => {
|
|
9
|
+
if (env.SELF_HOSTED) {
|
|
10
|
+
const designDoc = await db.get("_design/database")
|
|
11
|
+
return designDoc.views[viewName]
|
|
12
|
+
} else {
|
|
13
|
+
const viewDoc = await db.get(generateMemoryViewID(viewName))
|
|
14
|
+
return viewDoc.view
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
exports.getViews = async db => {
|
|
19
|
+
const response = []
|
|
20
|
+
if (env.SELF_HOSTED) {
|
|
21
|
+
const designDoc = await db.get("_design/database")
|
|
22
|
+
for (let name of Object.keys(designDoc.views)) {
|
|
23
|
+
// Only return custom views, not built ins
|
|
24
|
+
if (Object.values(ViewNames).indexOf(name) !== -1) {
|
|
25
|
+
continue
|
|
26
|
+
}
|
|
27
|
+
response.push({
|
|
28
|
+
name,
|
|
29
|
+
...designDoc.views[name],
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
const views = (
|
|
34
|
+
await db.allDocs(
|
|
35
|
+
getMemoryViewParams({
|
|
36
|
+
include_docs: true,
|
|
37
|
+
})
|
|
38
|
+
)
|
|
39
|
+
).rows.map(row => row.doc)
|
|
40
|
+
for (let viewDoc of views) {
|
|
41
|
+
response.push({
|
|
42
|
+
name: viewDoc.name,
|
|
43
|
+
...viewDoc.view,
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return response
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
exports.saveView = async (db, originalName, viewName, viewTemplate) => {
|
|
51
|
+
if (env.SELF_HOSTED) {
|
|
52
|
+
const designDoc = await db.get("_design/database")
|
|
53
|
+
designDoc.views = {
|
|
54
|
+
...designDoc.views,
|
|
55
|
+
[viewName]: viewTemplate,
|
|
56
|
+
}
|
|
57
|
+
// view has been renamed
|
|
58
|
+
if (originalName) {
|
|
59
|
+
delete designDoc.views[originalName]
|
|
60
|
+
}
|
|
61
|
+
await db.put(designDoc)
|
|
62
|
+
} else {
|
|
63
|
+
const id = generateMemoryViewID(viewName)
|
|
64
|
+
const originalId = originalName ? generateMemoryViewID(originalName) : null
|
|
65
|
+
const viewDoc = {
|
|
66
|
+
_id: id,
|
|
67
|
+
view: viewTemplate,
|
|
68
|
+
name: viewName,
|
|
69
|
+
tableId: viewTemplate.meta.tableId,
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const old = await db.get(id)
|
|
73
|
+
if (originalId) {
|
|
74
|
+
const originalDoc = await db.get(originalId)
|
|
75
|
+
await db.remove(originalDoc._id, originalDoc._rev)
|
|
76
|
+
}
|
|
77
|
+
if (old && old._rev) {
|
|
78
|
+
viewDoc._rev = old._rev
|
|
79
|
+
}
|
|
80
|
+
} catch (err) {
|
|
81
|
+
// didn't exist, just skip
|
|
82
|
+
}
|
|
83
|
+
await db.put(viewDoc)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
exports.deleteView = async (db, viewName) => {
|
|
88
|
+
if (env.SELF_HOSTED) {
|
|
89
|
+
const designDoc = await db.get("_design/database")
|
|
90
|
+
const view = designDoc.views[viewName]
|
|
91
|
+
delete designDoc.views[viewName]
|
|
92
|
+
await db.put(designDoc)
|
|
93
|
+
return view
|
|
94
|
+
} else {
|
|
95
|
+
const id = generateMemoryViewID(viewName)
|
|
96
|
+
const viewDoc = await db.get(id)
|
|
97
|
+
await db.remove(viewDoc._id, viewDoc._rev)
|
|
98
|
+
return viewDoc.view
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
exports.migrateToInMemoryView = async (db, viewName) => {
|
|
103
|
+
// delete the view initially
|
|
104
|
+
const designDoc = await db.get("_design/database")
|
|
105
|
+
const view = designDoc.views[viewName]
|
|
106
|
+
delete designDoc.views[viewName]
|
|
107
|
+
await db.put(designDoc)
|
|
108
|
+
await exports.saveView(db, null, viewName, view)
|
|
109
|
+
}
|
|
@@ -205,7 +205,7 @@ describe("/views", () => {
|
|
|
205
205
|
})
|
|
206
206
|
|
|
207
207
|
describe("exportView", () => {
|
|
208
|
-
it("should be able to
|
|
208
|
+
it("should be able to export a view", async () => {
|
|
209
209
|
await config.createTable(priceTable())
|
|
210
210
|
await config.createRow()
|
|
211
211
|
const view = await config.createView()
|
|
@@ -2,6 +2,7 @@ const rowController = require("../../api/controllers/row")
|
|
|
2
2
|
const automationUtils = require("../automationUtils")
|
|
3
3
|
const env = require("../../environment")
|
|
4
4
|
const usage = require("../../utilities/usageQuota")
|
|
5
|
+
const { buildCtx } = require("./utils")
|
|
5
6
|
|
|
6
7
|
exports.definition = {
|
|
7
8
|
name: "Create Row",
|
|
@@ -69,16 +70,12 @@ exports.run = async function ({ inputs, appId, apiKey, emitter }) {
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
// have to clean up the row, remove the table from it
|
|
72
|
-
const ctx = {
|
|
73
|
+
const ctx = buildCtx(appId, emitter, {
|
|
74
|
+
body: inputs.row,
|
|
73
75
|
params: {
|
|
74
76
|
tableId: inputs.row.tableId,
|
|
75
77
|
},
|
|
76
|
-
|
|
77
|
-
body: inputs.row,
|
|
78
|
-
},
|
|
79
|
-
appId,
|
|
80
|
-
eventEmitter: emitter,
|
|
81
|
-
}
|
|
78
|
+
})
|
|
82
79
|
|
|
83
80
|
try {
|
|
84
81
|
inputs.row = await automationUtils.cleanUpRow(
|
|
@@ -86,7 +83,7 @@ exports.run = async function ({ inputs, appId, apiKey, emitter }) {
|
|
|
86
83
|
inputs.row.tableId,
|
|
87
84
|
inputs.row
|
|
88
85
|
)
|
|
89
|
-
if (env.
|
|
86
|
+
if (env.USE_QUOTAS) {
|
|
90
87
|
await usage.update(apiKey, usage.Properties.ROW, 1)
|
|
91
88
|
}
|
|
92
89
|
await rowController.save(ctx)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const rowController = require("../../api/controllers/row")
|
|
2
2
|
const env = require("../../environment")
|
|
3
3
|
const usage = require("../../utilities/usageQuota")
|
|
4
|
+
const { buildCtx } = require("./utils")
|
|
4
5
|
|
|
5
6
|
exports.definition = {
|
|
6
7
|
description: "Delete a row from your database",
|
|
@@ -60,19 +61,16 @@ exports.run = async function ({ inputs, appId, apiKey, emitter }) {
|
|
|
60
61
|
},
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
|
-
|
|
64
|
+
|
|
65
|
+
let ctx = buildCtx(appId, emitter, {
|
|
66
|
+
body: {
|
|
67
|
+
_id: inputs.id,
|
|
68
|
+
_rev: inputs.revision,
|
|
69
|
+
},
|
|
64
70
|
params: {
|
|
65
71
|
tableId: inputs.tableId,
|
|
66
72
|
},
|
|
67
|
-
|
|
68
|
-
body: {
|
|
69
|
-
_id: inputs.id,
|
|
70
|
-
_rev: inputs.revision,
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
appId,
|
|
74
|
-
eventEmitter: emitter,
|
|
75
|
-
}
|
|
73
|
+
})
|
|
76
74
|
|
|
77
75
|
try {
|
|
78
76
|
if (env.isProd()) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const rowController = require("../../api/controllers/row")
|
|
2
2
|
const tableController = require("../../api/controllers/table")
|
|
3
3
|
const { FieldTypes } = require("../../constants")
|
|
4
|
+
const { buildCtx } = require("./utils")
|
|
4
5
|
|
|
5
6
|
const SortOrders = {
|
|
6
7
|
ASCENDING: "ascending",
|
|
@@ -70,12 +71,11 @@ exports.definition = {
|
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
async function getTable(appId, tableId) {
|
|
73
|
-
const ctx = {
|
|
74
|
+
const ctx = buildCtx(appId, null, {
|
|
74
75
|
params: {
|
|
75
76
|
id: tableId,
|
|
76
77
|
},
|
|
77
|
-
|
|
78
|
-
}
|
|
78
|
+
})
|
|
79
79
|
await tableController.find(ctx)
|
|
80
80
|
return ctx.body
|
|
81
81
|
}
|
|
@@ -89,21 +89,18 @@ exports.run = async function ({ inputs, appId }) {
|
|
|
89
89
|
sortType =
|
|
90
90
|
fieldType === FieldTypes.NUMBER ? FieldTypes.NUMBER : FieldTypes.STRING
|
|
91
91
|
}
|
|
92
|
-
const ctx = {
|
|
92
|
+
const ctx = buildCtx(appId, null, {
|
|
93
93
|
params: {
|
|
94
94
|
tableId,
|
|
95
95
|
},
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
limit,
|
|
103
|
-
},
|
|
96
|
+
body: {
|
|
97
|
+
sortOrder,
|
|
98
|
+
sortType,
|
|
99
|
+
sort: sortColumn,
|
|
100
|
+
query: filters || {},
|
|
101
|
+
limit,
|
|
104
102
|
},
|
|
105
|
-
|
|
106
|
-
}
|
|
103
|
+
})
|
|
107
104
|
try {
|
|
108
105
|
await rowController.search(ctx)
|
|
109
106
|
return {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const rowController = require("../../api/controllers/row")
|
|
2
2
|
const automationUtils = require("../automationUtils")
|
|
3
|
+
const { buildCtx } = require("./utils")
|
|
3
4
|
|
|
4
5
|
exports.definition = {
|
|
5
6
|
name: "Update Row",
|
|
@@ -72,19 +73,15 @@ exports.run = async function ({ inputs, appId, emitter }) {
|
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
// have to clean up the row, remove the table from it
|
|
75
|
-
const ctx = {
|
|
76
|
+
const ctx = buildCtx(appId, emitter, {
|
|
77
|
+
body: {
|
|
78
|
+
...inputs.row,
|
|
79
|
+
_id: inputs.rowId,
|
|
80
|
+
},
|
|
76
81
|
params: {
|
|
77
82
|
rowId: inputs.rowId,
|
|
78
83
|
},
|
|
79
|
-
|
|
80
|
-
body: {
|
|
81
|
-
...inputs.row,
|
|
82
|
-
_id: inputs.rowId,
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
appId,
|
|
86
|
-
eventEmitter: emitter,
|
|
87
|
-
}
|
|
84
|
+
})
|
|
88
85
|
|
|
89
86
|
try {
|
|
90
87
|
inputs.row = await automationUtils.cleanUpRowById(
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const PouchDB = require("pouchdb")
|
|
2
|
+
const memory = require("pouchdb-adapter-memory")
|
|
3
|
+
const newid = require("./newid")
|
|
4
|
+
|
|
5
|
+
PouchDB.plugin(memory)
|
|
6
|
+
const Pouch = PouchDB.defaults({
|
|
7
|
+
prefix: undefined,
|
|
8
|
+
adapter: "memory",
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
exports.runView = async (view, calculation, group, data) => {
|
|
12
|
+
// use a different ID each time for the DB, make sure they
|
|
13
|
+
// are always unique for each query, don't want overlap
|
|
14
|
+
// which could cause 409s
|
|
15
|
+
const db = new Pouch(newid())
|
|
16
|
+
// write all the docs to the in memory Pouch (remove revs)
|
|
17
|
+
await db.bulkDocs(
|
|
18
|
+
data.map(row => ({
|
|
19
|
+
...row,
|
|
20
|
+
_rev: undefined,
|
|
21
|
+
}))
|
|
22
|
+
)
|
|
23
|
+
let fn = (doc, emit) => emit(doc._id)
|
|
24
|
+
eval("fn = " + view.map.replace("function (doc)", "function (doc, emit)"))
|
|
25
|
+
const queryFns = {
|
|
26
|
+
meta: view.meta,
|
|
27
|
+
map: fn,
|
|
28
|
+
}
|
|
29
|
+
if (view.reduce) {
|
|
30
|
+
queryFns.reduce = view.reduce
|
|
31
|
+
}
|
|
32
|
+
const response = await db.query(queryFns, {
|
|
33
|
+
include_docs: !calculation,
|
|
34
|
+
group: !!group,
|
|
35
|
+
})
|
|
36
|
+
// need to fix the revs to be totally accurate
|
|
37
|
+
for (let row of response.rows) {
|
|
38
|
+
if (!row._rev || !row._id) {
|
|
39
|
+
continue
|
|
40
|
+
}
|
|
41
|
+
const found = data.find(possible => possible._id === row._id)
|
|
42
|
+
if (found) {
|
|
43
|
+
row._rev = found._rev
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
await db.destroy()
|
|
47
|
+
return response
|
|
48
|
+
}
|
|
@@ -76,9 +76,12 @@ async function getFullLinkedDocs(ctx, appId, links) {
|
|
|
76
76
|
// create DBs
|
|
77
77
|
const db = new CouchDB(appId)
|
|
78
78
|
const linkedRowIds = links.map(link => link.id)
|
|
79
|
-
|
|
79
|
+
const uniqueRowIds = [...new Set(linkedRowIds)]
|
|
80
|
+
let dbRows = (await db.allDocs(getMultiIDParams(uniqueRowIds))).rows.map(
|
|
80
81
|
row => row.doc
|
|
81
82
|
)
|
|
83
|
+
// convert the unique db rows back to a full list of linked rows
|
|
84
|
+
const linked = linkedRowIds.map(id => dbRows.find(row => row._id === id))
|
|
82
85
|
// need to handle users as specific cases
|
|
83
86
|
let [users, other] = partition(linked, linkRow =>
|
|
84
87
|
linkRow._id.startsWith(USER_METDATA_PREFIX)
|
|
@@ -112,7 +115,7 @@ exports.updateLinks = async function (args) {
|
|
|
112
115
|
let linkController = new LinkController(args)
|
|
113
116
|
try {
|
|
114
117
|
if (
|
|
115
|
-
!(await linkController.doesTableHaveLinkedFields()) &&
|
|
118
|
+
!(await linkController.doesTableHaveLinkedFields(table)) &&
|
|
116
119
|
(oldTable == null ||
|
|
117
120
|
!(await linkController.doesTableHaveLinkedFields(oldTable)))
|
|
118
121
|
) {
|
package/src/db/utils.js
CHANGED
|
@@ -39,6 +39,7 @@ const DocumentTypes = {
|
|
|
39
39
|
QUERY: "query",
|
|
40
40
|
DEPLOYMENTS: "deployments",
|
|
41
41
|
METADATA: "metadata",
|
|
42
|
+
MEM_VIEW: "view",
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
const ViewNames = {
|
|
@@ -348,6 +349,14 @@ exports.getMetadataParams = (type, entityId = null, otherProps = {}) => {
|
|
|
348
349
|
return getDocParams(DocumentTypes.METADATA, docId, otherProps)
|
|
349
350
|
}
|
|
350
351
|
|
|
352
|
+
exports.generateMemoryViewID = viewName => {
|
|
353
|
+
return `${DocumentTypes.MEM_VIEW}${SEPARATOR}${viewName}`
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
exports.getMemoryViewParams = (otherProps = {}) => {
|
|
357
|
+
return getDocParams(DocumentTypes.MEM_VIEW, null, otherProps)
|
|
358
|
+
}
|
|
359
|
+
|
|
351
360
|
/**
|
|
352
361
|
* This can be used with the db.allDocs to get a list of IDs
|
|
353
362
|
*/
|
package/src/environment.js
CHANGED
|
@@ -26,7 +26,7 @@ module.exports = {
|
|
|
26
26
|
COUCH_DB_URL: process.env.COUCH_DB_URL,
|
|
27
27
|
MINIO_URL: process.env.MINIO_URL,
|
|
28
28
|
WORKER_URL: process.env.WORKER_URL,
|
|
29
|
-
SELF_HOSTED:
|
|
29
|
+
SELF_HOSTED: process.env.SELF_HOSTED,
|
|
30
30
|
AWS_REGION: process.env.AWS_REGION,
|
|
31
31
|
ENABLE_ANALYTICS: process.env.ENABLE_ANALYTICS,
|
|
32
32
|
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
|
|
@@ -66,3 +66,10 @@ module.exports = {
|
|
|
66
66
|
return !isDev()
|
|
67
67
|
},
|
|
68
68
|
}
|
|
69
|
+
|
|
70
|
+
// convert any strings to numbers if required, like "0" would be true otherwise
|
|
71
|
+
for (let [key, value] of Object.entries(module.exports)) {
|
|
72
|
+
if (typeof value === "string" && !isNaN(parseInt(value))) {
|
|
73
|
+
module.exports[key] = parseInt(value)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -12,7 +12,7 @@ import { getSqlQuery } from "./utils"
|
|
|
12
12
|
module MySQLModule {
|
|
13
13
|
const mysql = require("mysql")
|
|
14
14
|
const Sql = require("./base/sql")
|
|
15
|
-
const { buildExternalTableId, convertType } = require("./utils")
|
|
15
|
+
const { buildExternalTableId, convertType, copyExistingPropsOver } = require("./utils")
|
|
16
16
|
const { FieldTypes } = require("../constants")
|
|
17
17
|
|
|
18
18
|
interface MySQLConfig {
|
|
@@ -194,18 +194,7 @@ module MySQLModule {
|
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
if (entities && entities[tableName]) {
|
|
199
|
-
const existingTableSchema = entities[tableName].schema
|
|
200
|
-
for (let key in existingTableSchema) {
|
|
201
|
-
if (!existingTableSchema.hasOwnProperty(key)) {
|
|
202
|
-
continue
|
|
203
|
-
}
|
|
204
|
-
if (existingTableSchema[key].type === "link") {
|
|
205
|
-
tables[tableName].schema[key] = existingTableSchema[key]
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
197
|
+
copyExistingPropsOver(tableName, tables, entities)
|
|
209
198
|
}
|
|
210
199
|
|
|
211
200
|
this.client.end()
|
|
@@ -12,7 +12,7 @@ module PostgresModule {
|
|
|
12
12
|
const { Pool } = require("pg")
|
|
13
13
|
const Sql = require("./base/sql")
|
|
14
14
|
const { FieldTypes } = require("../constants")
|
|
15
|
-
const { buildExternalTableId, convertType } = require("./utils")
|
|
15
|
+
const { buildExternalTableId, convertType, copyExistingPropsOver } = require("./utils")
|
|
16
16
|
|
|
17
17
|
interface PostgresConfig {
|
|
18
18
|
host: string
|
|
@@ -173,31 +173,24 @@ module PostgresModule {
|
|
|
173
173
|
name: tableName,
|
|
174
174
|
schema: {},
|
|
175
175
|
}
|
|
176
|
-
|
|
177
|
-
// add the existing relationships from the entities if they exist, to prevent them from being overridden
|
|
178
|
-
if (entities && entities[tableName]) {
|
|
179
|
-
const existingTableSchema = entities[tableName].schema
|
|
180
|
-
for (let key in existingTableSchema) {
|
|
181
|
-
if (!existingTableSchema.hasOwnProperty(key)) {
|
|
182
|
-
continue
|
|
183
|
-
}
|
|
184
|
-
if (existingTableSchema[key].type === "link") {
|
|
185
|
-
tables[tableName].schema[key] = existingTableSchema[key]
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
176
|
}
|
|
190
177
|
|
|
191
178
|
const type: string = convertType(column.data_type, TYPE_MAP)
|
|
192
|
-
const
|
|
193
|
-
|
|
179
|
+
const identity = !!(column.identity_generation || column.identity_start || column.identity_increment)
|
|
180
|
+
const hasDefault = typeof column.column_default === "string" &&
|
|
194
181
|
column.column_default.startsWith("nextval")
|
|
182
|
+
const isGenerated = column.is_generated && column.is_generated !== "NEVER"
|
|
183
|
+
const isAuto: boolean = hasDefault || identity || isGenerated
|
|
195
184
|
tables[tableName].schema[columnName] = {
|
|
196
185
|
autocolumn: isAuto,
|
|
197
186
|
name: columnName,
|
|
198
187
|
type,
|
|
199
188
|
}
|
|
200
189
|
}
|
|
190
|
+
|
|
191
|
+
for (let tableName of Object.keys(tables)) {
|
|
192
|
+
copyExistingPropsOver(tableName, tables, entities)
|
|
193
|
+
}
|
|
201
194
|
this.tables = tables
|
|
202
195
|
}
|
|
203
196
|
|