@budibase/server 0.9.140-alpha.4 → 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.
Files changed (200) hide show
  1. package/builder/assets/{index.2bcd18f5.js → index.80d850d1.js} +1 -1
  2. package/builder/index.html +1 -1
  3. package/coverage/clover.xml +646 -528
  4. package/coverage/coverage-final.json +17 -15
  5. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  6. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  7. package/coverage/lcov-report/api/controllers/application.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/datasource.js.html +3 -3
  13. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/hosting.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/index.html +1 -1
  16. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/query.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/row/index.html +19 -19
  25. package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/internal.js.html +242 -47
  27. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  32. package/coverage/lcov-report/api/controllers/table/index.js.html +2 -2
  33. package/coverage/lcov-report/api/controllers/table/utils.js.html +31 -19
  34. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/view/index.html +32 -17
  38. package/coverage/lcov-report/api/controllers/view/index.js.html +84 -186
  39. package/coverage/lcov-report/api/controllers/view/utils.js.html +407 -0
  40. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  42. package/coverage/lcov-report/api/index.html +1 -1
  43. package/coverage/lcov-report/api/index.js.html +1 -1
  44. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  45. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  46. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  47. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  48. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  49. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/index.html +1 -1
  56. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/static.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  73. package/coverage/lcov-report/automations/actions.js.html +1 -1
  74. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  75. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  76. package/coverage/lcov-report/automations/index.html +1 -1
  77. package/coverage/lcov-report/automations/index.js.html +1 -1
  78. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  79. package/coverage/lcov-report/automations/steps/createRow.js.html +10 -19
  80. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  81. package/coverage/lcov-report/automations/steps/deleteRow.js.html +14 -20
  82. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/index.html +31 -31
  87. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/queryRows.js.html +18 -27
  90. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/updateRow.js.html +12 -21
  94. package/coverage/lcov-report/automations/steps/utils.js.html +23 -23
  95. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  96. package/coverage/lcov-report/automations/thread.js.html +1 -1
  97. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  98. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  106. package/coverage/lcov-report/automations/utils.js.html +1 -1
  107. package/coverage/lcov-report/constants/index.html +1 -1
  108. package/coverage/lcov-report/constants/index.js.html +1 -1
  109. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  110. package/coverage/lcov-report/constants/screens.js.html +1 -1
  111. package/coverage/lcov-report/db/client.js.html +1 -1
  112. package/coverage/lcov-report/db/inMemoryView.js.html +224 -0
  113. package/coverage/lcov-report/db/index.html +34 -19
  114. package/coverage/lcov-report/db/index.js.html +1 -1
  115. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +4 -4
  116. package/coverage/lcov-report/db/linkedRows/index.html +14 -14
  117. package/coverage/lcov-report/db/linkedRows/index.js.html +18 -9
  118. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  119. package/coverage/lcov-report/db/newid.js.html +1 -1
  120. package/coverage/lcov-report/db/utils.js.html +37 -10
  121. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  122. package/coverage/lcov-report/events/index.html +1 -1
  123. package/coverage/lcov-report/events/index.js.html +1 -1
  124. package/coverage/lcov-report/events/utils.js.html +1 -1
  125. package/coverage/lcov-report/index.html +65 -65
  126. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  127. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  128. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  129. package/coverage/lcov-report/middleware/authorized.js.html +1 -1
  130. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  131. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  132. package/coverage/lcov-report/middleware/index.html +1 -1
  133. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  134. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  135. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  136. package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
  137. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  138. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  139. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  140. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  141. package/coverage/lcov-report/utilities/global.js.html +1 -1
  142. package/coverage/lcov-report/utilities/index.html +1 -1
  143. package/coverage/lcov-report/utilities/index.js.html +1 -1
  144. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  145. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  146. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  147. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  148. package/coverage/lcov-report/utilities/rowProcessor/index.html +15 -15
  149. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +58 -13
  150. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  151. package/coverage/lcov-report/utilities/security.js.html +2 -2
  152. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  153. package/coverage/lcov-report/utilities/users.js.html +1 -1
  154. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  155. package/coverage/lcov.info +1093 -883
  156. package/dist/api/controllers/datasource.js +2 -2
  157. package/dist/api/controllers/row/ExternalRequest.js +4 -0
  158. package/dist/api/controllers/row/internal.js +97 -23
  159. package/dist/api/controllers/table/index.js +1 -1
  160. package/dist/api/controllers/table/utils.js +13 -11
  161. package/dist/api/controllers/view/index.js +74 -96
  162. package/dist/api/controllers/view/utils.js +102 -0
  163. package/dist/automations/steps/createRow.js +5 -8
  164. package/dist/automations/steps/deleteRow.js +7 -10
  165. package/dist/automations/steps/queryRows.js +11 -14
  166. package/dist/automations/steps/updateRow.js +4 -7
  167. package/dist/db/inMemoryView.js +51 -0
  168. package/dist/db/linkedRows/index.js +5 -2
  169. package/dist/db/utils.js +7 -0
  170. package/dist/environment.js +7 -1
  171. package/dist/integrations/mysql.js +2 -13
  172. package/dist/integrations/postgres.js +8 -14
  173. package/dist/integrations/utils.js +19 -1
  174. package/dist/package.json +5 -5
  175. package/dist/tsconfig.tsbuildinfo +1 -1
  176. package/dist/utilities/rowProcessor/index.js +10 -5
  177. package/package.json +6 -6
  178. package/scripts/integrations/service-vehicles/docker-compose.yml +28 -0
  179. package/scripts/integrations/service-vehicles/init.sql +52 -0
  180. package/scripts/integrations/service-vehicles/reset.sh +3 -0
  181. package/src/api/controllers/datasource.js +2 -2
  182. package/src/api/controllers/row/ExternalRequest.ts +5 -1
  183. package/src/api/controllers/row/internal.js +88 -23
  184. package/src/api/controllers/table/index.js +1 -1
  185. package/src/api/controllers/table/utils.js +16 -12
  186. package/src/api/controllers/view/index.js +82 -116
  187. package/src/api/controllers/view/utils.js +109 -0
  188. package/src/api/routes/tests/view.spec.js +1 -1
  189. package/src/automations/steps/createRow.js +5 -8
  190. package/src/automations/steps/deleteRow.js +8 -10
  191. package/src/automations/steps/queryRows.js +11 -14
  192. package/src/automations/steps/updateRow.js +7 -10
  193. package/src/db/inMemoryView.js +48 -0
  194. package/src/db/linkedRows/index.js +5 -2
  195. package/src/db/utils.js +9 -0
  196. package/src/environment.js +8 -1
  197. package/src/integrations/mysql.ts +2 -13
  198. package/src/integrations/postgres.ts +9 -16
  199. package/src/integrations/utils.ts +18 -0
  200. package/src/utilities/rowProcessor/index.js +20 -5
@@ -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 delete a view", async () => {
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
- request: {
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.isProd()) {
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
- let ctx = {
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
- request: {
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
- appId,
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
- request: {
97
- body: {
98
- sortOrder,
99
- sortType,
100
- sort: sortColumn,
101
- query: filters || {},
102
- limit,
103
- },
96
+ body: {
97
+ sortOrder,
98
+ sortType,
99
+ sort: sortColumn,
100
+ query: filters || {},
101
+ limit,
104
102
  },
105
- appId,
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
- request: {
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
- let linked = (await db.allDocs(getMultiIDParams(linkedRowIds))).rows.map(
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
  */
@@ -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: !!parseInt(process.env.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
- // add the existing relationships from the entities if they exist, to prevent them from being overridden
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 isAuto: boolean =
193
- typeof column.column_default === "string" &&
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
 
@@ -82,3 +82,21 @@ export function isIsoDateString(str: string) {
82
82
  let d = new Date(str)
83
83
  return d.toISOString() === str
84
84
  }
85
+
86
+ // add the existing relationships from the entities if they exist, to prevent them from being overridden
87
+ export function copyExistingPropsOver(tableName: string, tables: { [key: string]: any }, entities: { [key: string]: any }) {
88
+ if (entities && entities[tableName]) {
89
+ if (entities[tableName].primaryDisplay) {
90
+ tables[tableName].primaryDisplay = entities[tableName].primaryDisplay
91
+ }
92
+ const existingTableSchema = entities[tableName].schema
93
+ for (let key in existingTableSchema) {
94
+ if (!existingTableSchema.hasOwnProperty(key)) {
95
+ continue
96
+ }
97
+ if (existingTableSchema[key].type === "link") {
98
+ tables[tableName].schema[key] = existingTableSchema[key]
99
+ }
100
+ }
101
+ }
102
+ }
@@ -89,10 +89,16 @@ const TYPE_TRANSFORM_MAP = {
89
89
  * @param {Object} user The user to be used for an appId as well as the createdBy and createdAt fields.
90
90
  * @param {Object} table The table which is to be used for the schema, as well as handling auto IDs incrementing.
91
91
  * @param {Object} row The row which is to be updated with information for the auto columns.
92
+ * @param {Object} opts specific options for function to carry out optional features.
92
93
  * @returns {{row: Object, table: Object}} The updated row and table, the table may need to be updated
93
94
  * for automatic ID purposes.
94
95
  */
95
- function processAutoColumn(user, table, row) {
96
+ function processAutoColumn(
97
+ user,
98
+ table,
99
+ row,
100
+ opts = { reprocessing: false, noAutoRelationships: false }
101
+ ) {
96
102
  let now = new Date().toISOString()
97
103
  // if a row doesn't have a revision then it doesn't exist yet
98
104
  const creating = !row._rev
@@ -102,7 +108,7 @@ function processAutoColumn(user, table, row) {
102
108
  }
103
109
  switch (schema.subtype) {
104
110
  case AutoFieldSubTypes.CREATED_BY:
105
- if (creating) {
111
+ if (creating && !opts.reprocessing && !opts.noAutoRelationships) {
106
112
  row[key] = [user.userId]
107
113
  }
108
114
  break
@@ -112,7 +118,9 @@ function processAutoColumn(user, table, row) {
112
118
  }
113
119
  break
114
120
  case AutoFieldSubTypes.UPDATED_BY:
115
- row[key] = [user.userId]
121
+ if (!opts.reprocessing && !opts.noAutoRelationships) {
122
+ row[key] = [user.userId]
123
+ }
116
124
  break
117
125
  case AutoFieldSubTypes.UPDATED_AT:
118
126
  row[key] = now
@@ -127,6 +135,7 @@ function processAutoColumn(user, table, row) {
127
135
  }
128
136
  return { table, row }
129
137
  }
138
+ exports.processAutoColumn = processAutoColumn
130
139
 
131
140
  /**
132
141
  * This will coerce a value to the correct types based on the type transform map
@@ -151,9 +160,15 @@ exports.coerce = (row, type) => {
151
160
  * @param {object} user the user which is performing the input.
152
161
  * @param {object} row the row which is being created/updated.
153
162
  * @param {object} table the table which the row is being saved to.
163
+ * @param {object} opts some input processing options (like disabling auto-column relationships).
154
164
  * @returns {object} the row which has been prepared to be written to the DB.
155
165
  */
156
- exports.inputProcessing = (user = {}, table, row) => {
166
+ exports.inputProcessing = (
167
+ user = {},
168
+ table,
169
+ row,
170
+ opts = { noAutoRelationships: false }
171
+ ) => {
157
172
  let clonedRow = cloneDeep(row)
158
173
  // need to copy the table so it can be differenced on way out
159
174
  const copiedTable = cloneDeep(table)
@@ -176,7 +191,7 @@ exports.inputProcessing = (user = {}, table, row) => {
176
191
  }
177
192
  }
178
193
  // handle auto columns - this returns an object like {table, row}
179
- return processAutoColumn(user, copiedTable, clonedRow)
194
+ return processAutoColumn(user, copiedTable, clonedRow, opts)
180
195
  }
181
196
 
182
197
  /**