@budibase/server 2.5.9 → 2.5.10-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/builder/assets/index.24635afb.js +1794 -0
  2. package/builder/assets/index.4eae16b2.css +6 -0
  3. package/builder/index.html +2 -2
  4. package/dist/api/controllers/application.js +3 -4
  5. package/dist/api/controllers/automation.js +13 -7
  6. package/dist/api/controllers/datasource.js +1 -1
  7. package/dist/api/controllers/dev.js +1 -1
  8. package/dist/api/controllers/ops.js +40 -0
  9. package/dist/api/controllers/plugin/index.js +6 -37
  10. package/dist/api/controllers/query/index.js +2 -2
  11. package/dist/api/controllers/row/ExternalRequest.js +21 -14
  12. package/dist/api/controllers/table/utils.js +9 -3
  13. package/dist/api/controllers/user.js +1 -83
  14. package/dist/api/index.js +1 -2
  15. package/dist/api/routes/index.js +2 -2
  16. package/dist/api/routes/{cloud.js → ops.js} +19 -6
  17. package/dist/api/routes/user.js +0 -1
  18. package/dist/app.js +4 -13
  19. package/dist/automations/actions.js +32 -6
  20. package/dist/automations/index.js +3 -2
  21. package/dist/automations/steps/bash.js +6 -6
  22. package/dist/automations/steps/createRow.js +11 -11
  23. package/dist/automations/steps/delay.js +3 -3
  24. package/dist/automations/steps/deleteRow.js +8 -8
  25. package/dist/automations/steps/discord.js +8 -8
  26. package/dist/automations/steps/executeQuery.js +9 -9
  27. package/dist/automations/steps/executeScript.js +6 -6
  28. package/dist/automations/steps/filter.js +6 -6
  29. package/dist/automations/steps/integromat.js +10 -10
  30. package/dist/automations/steps/loop.js +9 -9
  31. package/dist/automations/steps/outgoingWebhook.js +10 -10
  32. package/dist/automations/steps/queryRows.js +14 -14
  33. package/dist/automations/steps/sendSmtpEmail.js +9 -9
  34. package/dist/automations/steps/serverLog.js +4 -4
  35. package/dist/automations/steps/slack.js +6 -6
  36. package/dist/automations/steps/updateRow.js +11 -11
  37. package/dist/automations/steps/zapier.js +9 -9
  38. package/dist/automations/triggerInfo/app.js +5 -5
  39. package/dist/automations/triggerInfo/cron.js +4 -4
  40. package/dist/automations/triggerInfo/rowDeleted.js +5 -5
  41. package/dist/automations/triggerInfo/rowSaved.js +7 -7
  42. package/dist/automations/triggerInfo/rowUpdated.js +7 -7
  43. package/dist/automations/triggerInfo/webhook.js +6 -6
  44. package/dist/db/utils.js +3 -2
  45. package/dist/environment.js +0 -1
  46. package/dist/events/docUpdates/index.js +17 -0
  47. package/dist/events/docUpdates/processors.js +18 -0
  48. package/dist/events/docUpdates/syncUsers.js +49 -0
  49. package/dist/events/index.js +3 -0
  50. package/dist/integrations/base/sqlTable.js +9 -2
  51. package/dist/integrations/index.js +3 -3
  52. package/dist/integrations/microsoftSqlServer.js +5 -2
  53. package/dist/integrations/mysql.js +5 -3
  54. package/dist/integrations/postgres.js +7 -5
  55. package/dist/integrations/redis.js +7 -0
  56. package/dist/integrations/rest.js +4 -0
  57. package/dist/migrations/functions/syncQuotas.js +2 -0
  58. package/dist/migrations/functions/usageQuotas/syncApps.js +1 -2
  59. package/dist/migrations/functions/usageQuotas/syncRows.js +1 -2
  60. package/dist/migrations/functions/usageQuotas/syncUsers.js +21 -0
  61. package/dist/sdk/app/applications/sync.js +117 -23
  62. package/dist/sdk/app/backups/exports.js +14 -38
  63. package/dist/sdk/index.js +2 -0
  64. package/dist/sdk/plugins/index.js +27 -0
  65. package/dist/sdk/plugins/plugins.js +53 -0
  66. package/dist/sdk/users/utils.js +21 -4
  67. package/dist/startup.js +31 -28
  68. package/dist/threads/automation.js +16 -5
  69. package/dist/tsconfig.build.tsbuildinfo +1 -1
  70. package/dist/utilities/fileSystem/plugin.js +33 -23
  71. package/dist/utilities/global.js +17 -12
  72. package/dist/utilities/rowProcessor/utils.js +4 -5
  73. package/dist/watch.js +2 -2
  74. package/dist/websockets/client.js +14 -0
  75. package/dist/websockets/grid.js +60 -0
  76. package/dist/websockets/index.js +17 -0
  77. package/dist/websockets/websocket.js +78 -0
  78. package/package.json +16 -16
  79. package/scripts/dev/manage.js +2 -0
  80. package/scripts/integrations/mssql/data/entrypoint.sh +1 -0
  81. package/scripts/integrations/mssql/data/setup.sql +17 -17
  82. package/scripts/integrations/mysql/init.sql +1 -1
  83. package/scripts/integrations/postgres/init.sql +1 -0
  84. package/src/api/controllers/application.ts +4 -4
  85. package/src/api/controllers/automation.ts +12 -6
  86. package/src/api/controllers/datasource.ts +15 -5
  87. package/src/api/controllers/dev.ts +2 -2
  88. package/src/api/controllers/ops.ts +32 -0
  89. package/src/api/controllers/plugin/index.ts +8 -45
  90. package/src/api/controllers/query/index.ts +2 -2
  91. package/src/api/controllers/row/ExternalRequest.ts +21 -12
  92. package/src/api/controllers/row/internal.ts +9 -10
  93. package/src/api/controllers/row/utils.ts +2 -2
  94. package/src/api/controllers/table/utils.ts +10 -3
  95. package/src/api/controllers/user.ts +10 -96
  96. package/src/api/index.ts +2 -4
  97. package/src/api/routes/index.ts +2 -2
  98. package/src/api/routes/ops.ts +30 -0
  99. package/src/api/routes/tests/automation.spec.js +7 -4
  100. package/src/api/routes/tests/user.spec.js +48 -37
  101. package/src/api/routes/user.ts +0 -5
  102. package/src/app.ts +4 -15
  103. package/src/automations/actions.ts +56 -24
  104. package/src/automations/index.ts +1 -1
  105. package/src/automations/steps/bash.ts +10 -7
  106. package/src/automations/steps/createRow.ts +15 -12
  107. package/src/automations/steps/delay.ts +6 -4
  108. package/src/automations/steps/deleteRow.ts +12 -9
  109. package/src/automations/steps/discord.ts +10 -8
  110. package/src/automations/steps/executeQuery.ts +13 -10
  111. package/src/automations/steps/executeScript.ts +10 -7
  112. package/src/automations/steps/filter.ts +8 -6
  113. package/src/automations/steps/integromat.ts +12 -10
  114. package/src/automations/steps/loop.ts +16 -10
  115. package/src/automations/steps/outgoingWebhook.ts +14 -11
  116. package/src/automations/steps/queryRows.ts +18 -15
  117. package/src/automations/steps/sendSmtpEmail.ts +11 -9
  118. package/src/automations/steps/serverLog.ts +6 -4
  119. package/src/automations/steps/slack.ts +8 -6
  120. package/src/automations/steps/updateRow.ts +15 -12
  121. package/src/automations/steps/zapier.ts +11 -9
  122. package/src/automations/tests/utilities/index.ts +2 -2
  123. package/src/automations/triggerInfo/app.ts +8 -5
  124. package/src/automations/triggerInfo/cron.ts +7 -4
  125. package/src/automations/triggerInfo/rowDeleted.ts +8 -5
  126. package/src/automations/triggerInfo/rowSaved.ts +10 -7
  127. package/src/automations/triggerInfo/rowUpdated.ts +10 -7
  128. package/src/automations/triggerInfo/webhook.ts +9 -6
  129. package/src/db/utils.ts +1 -0
  130. package/src/environment.ts +0 -1
  131. package/src/events/docUpdates/index.ts +1 -0
  132. package/src/events/docUpdates/processors.ts +14 -0
  133. package/src/events/docUpdates/syncUsers.ts +35 -0
  134. package/src/events/index.ts +1 -0
  135. package/src/integration-test/postgres.spec.ts +3 -1
  136. package/src/integrations/base/sqlTable.ts +9 -2
  137. package/src/integrations/index.ts +3 -3
  138. package/src/integrations/microsoftSqlServer.ts +5 -2
  139. package/src/integrations/mysql.ts +5 -3
  140. package/src/integrations/postgres.ts +7 -5
  141. package/src/integrations/redis.ts +8 -0
  142. package/src/integrations/rest.ts +3 -0
  143. package/src/migrations/functions/syncQuotas.ts +2 -0
  144. package/src/migrations/functions/usageQuotas/syncApps.ts +2 -3
  145. package/src/migrations/functions/usageQuotas/syncRows.ts +2 -3
  146. package/src/migrations/functions/usageQuotas/syncUsers.ts +9 -0
  147. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +2 -2
  148. package/src/migrations/functions/usageQuotas/tests/syncUsers.spec.ts +26 -0
  149. package/src/migrations/index.ts +1 -0
  150. package/src/sdk/app/applications/sync.ts +129 -22
  151. package/src/sdk/app/applications/tests/sync.spec.ts +137 -0
  152. package/src/sdk/app/backups/exports.ts +17 -41
  153. package/src/sdk/index.ts +2 -0
  154. package/src/sdk/plugins/index.ts +5 -0
  155. package/src/sdk/plugins/plugins.ts +41 -0
  156. package/src/sdk/users/tests/utils.spec.ts +1 -32
  157. package/src/sdk/users/utils.ts +23 -5
  158. package/src/startup.ts +36 -34
  159. package/src/tests/jestEnv.ts +0 -1
  160. package/src/tests/jestSetup.ts +0 -1
  161. package/src/tests/utilities/TestConfiguration.ts +28 -0
  162. package/src/tests/utilities/structures.ts +25 -17
  163. package/src/threads/automation.ts +18 -6
  164. package/src/utilities/fileSystem/plugin.ts +13 -4
  165. package/src/utilities/global.ts +21 -16
  166. package/src/utilities/rowProcessor/utils.ts +9 -10
  167. package/src/watch.ts +2 -2
  168. package/src/websockets/client.ts +11 -0
  169. package/src/websockets/grid.ts +55 -0
  170. package/src/websockets/index.ts +14 -0
  171. package/src/websockets/websocket.ts +83 -0
  172. package/tsconfig.build.json +3 -5
  173. package/tsconfig.json +2 -1
  174. package/builder/assets/index.0b358332.js +0 -1817
  175. package/builder/assets/index.7f9a008b.css +0 -6
  176. package/dist/api/controllers/cloud.js +0 -130
  177. package/dist/elasticApm.js +0 -14
  178. package/dist/package.json +0 -180
  179. package/dist/websocket.js +0 -22
  180. package/scripts/likeCypress.ts +0 -35
  181. package/src/api/controllers/cloud.ts +0 -119
  182. package/src/api/routes/cloud.ts +0 -18
  183. package/src/api/routes/tests/cloud.spec.ts +0 -54
  184. package/src/elasticApm.ts +0 -10
  185. package/src/migrations/functions/tests/syncQuotas.spec.js +0 -26
  186. package/src/tests/logging.ts +0 -34
  187. package/src/websocket.ts +0 -26
@@ -1,6 +1,6 @@
1
1
  import TestConfig from "../../../tests/utilities/TestConfiguration"
2
2
  import { context } from "@budibase/backend-core"
3
- import { ACTION_DEFINITIONS, getAction } from "../../actions"
3
+ import { BUILTIN_ACTION_DEFINITIONS, getAction } from "../../actions"
4
4
  import emitter from "../../../events/index"
5
5
  import env from "../../../environment"
6
6
 
@@ -57,4 +57,4 @@ export async function runStep(stepId: string, inputs: any, stepContext?: any) {
57
57
  }
58
58
 
59
59
  export const apiKey = "test"
60
- export const actions = ACTION_DEFINITIONS
60
+ export const actions = BUILTIN_ACTION_DEFINITIONS
@@ -1,4 +1,7 @@
1
1
  import {
2
+ AutomationCustomIOType,
3
+ AutomationIOType,
4
+ AutomationStepType,
2
5
  AutomationTriggerSchema,
3
6
  AutomationTriggerStepId,
4
7
  } from "@budibase/types"
@@ -15,8 +18,8 @@ export const definition: AutomationTriggerSchema = {
15
18
  inputs: {
16
19
  properties: {
17
20
  fields: {
18
- type: "object",
19
- customType: "triggerSchema",
21
+ type: AutomationIOType.OBJECT,
22
+ customType: AutomationCustomIOType.TRIGGER_SCHEMA,
20
23
  title: "Fields",
21
24
  },
22
25
  },
@@ -25,13 +28,13 @@ export const definition: AutomationTriggerSchema = {
25
28
  outputs: {
26
29
  properties: {
27
30
  fields: {
28
- type: "object",
31
+ type: AutomationIOType.OBJECT,
29
32
  description: "Fields submitted from the app frontend",
30
- customType: "triggerSchema",
33
+ customType: AutomationCustomIOType.TRIGGER_SCHEMA,
31
34
  },
32
35
  },
33
36
  required: ["fields"],
34
37
  },
35
38
  },
36
- type: "TRIGGER",
39
+ type: AutomationStepType.TRIGGER,
37
40
  }
@@ -1,4 +1,7 @@
1
1
  import {
2
+ AutomationCustomIOType,
3
+ AutomationIOType,
4
+ AutomationStepType,
2
5
  AutomationTriggerSchema,
3
6
  AutomationTriggerStepId,
4
7
  } from "@budibase/types"
@@ -15,8 +18,8 @@ export const definition: AutomationTriggerSchema = {
15
18
  inputs: {
16
19
  properties: {
17
20
  cron: {
18
- type: "string",
19
- customType: "cron",
21
+ type: AutomationIOType.STRING,
22
+ customType: AutomationCustomIOType.CRON,
20
23
  title: "Expression",
21
24
  },
22
25
  },
@@ -25,12 +28,12 @@ export const definition: AutomationTriggerSchema = {
25
28
  outputs: {
26
29
  properties: {
27
30
  timestamp: {
28
- type: "number",
31
+ type: AutomationIOType.NUMBER,
29
32
  description: "Timestamp the cron was executed",
30
33
  },
31
34
  },
32
35
  required: ["timestamp"],
33
36
  },
34
37
  },
35
- type: "TRIGGER",
38
+ type: AutomationStepType.TRIGGER,
36
39
  }
@@ -1,4 +1,7 @@
1
1
  import {
2
+ AutomationCustomIOType,
3
+ AutomationIOType,
4
+ AutomationStepType,
2
5
  AutomationTriggerSchema,
3
6
  AutomationTriggerStepId,
4
7
  } from "@budibase/types"
@@ -15,8 +18,8 @@ export const definition: AutomationTriggerSchema = {
15
18
  inputs: {
16
19
  properties: {
17
20
  tableId: {
18
- type: "string",
19
- customType: "table",
21
+ type: AutomationIOType.STRING,
22
+ customType: AutomationCustomIOType.TABLE,
20
23
  title: "Table",
21
24
  },
22
25
  },
@@ -25,13 +28,13 @@ export const definition: AutomationTriggerSchema = {
25
28
  outputs: {
26
29
  properties: {
27
30
  row: {
28
- type: "object",
29
- customType: "row",
31
+ type: AutomationIOType.OBJECT,
32
+ customType: AutomationCustomIOType.ROW,
30
33
  description: "The row that was deleted",
31
34
  },
32
35
  },
33
36
  required: ["row"],
34
37
  },
35
38
  },
36
- type: "TRIGGER",
39
+ type: AutomationStepType.TRIGGER,
37
40
  }
@@ -1,4 +1,7 @@
1
1
  import {
2
+ AutomationCustomIOType,
3
+ AutomationIOType,
4
+ AutomationStepType,
2
5
  AutomationTriggerSchema,
3
6
  AutomationTriggerStepId,
4
7
  } from "@budibase/types"
@@ -15,8 +18,8 @@ export const definition: AutomationTriggerSchema = {
15
18
  inputs: {
16
19
  properties: {
17
20
  tableId: {
18
- type: "string",
19
- customType: "table",
21
+ type: AutomationIOType.STRING,
22
+ customType: AutomationCustomIOType.TABLE,
20
23
  title: "Table",
21
24
  },
22
25
  },
@@ -25,21 +28,21 @@ export const definition: AutomationTriggerSchema = {
25
28
  outputs: {
26
29
  properties: {
27
30
  row: {
28
- type: "object",
29
- customType: "row",
31
+ type: AutomationIOType.OBJECT,
32
+ customType: AutomationCustomIOType.ROW,
30
33
  description: "The new row that was created",
31
34
  },
32
35
  id: {
33
- type: "string",
36
+ type: AutomationIOType.STRING,
34
37
  description: "Row ID - can be used for updating",
35
38
  },
36
39
  revision: {
37
- type: "string",
40
+ type: AutomationIOType.STRING,
38
41
  description: "Revision of row",
39
42
  },
40
43
  },
41
44
  required: ["row", "id"],
42
45
  },
43
46
  },
44
- type: "TRIGGER",
47
+ type: AutomationStepType.TRIGGER,
45
48
  }
@@ -1,4 +1,7 @@
1
1
  import {
2
+ AutomationCustomIOType,
3
+ AutomationIOType,
4
+ AutomationStepType,
2
5
  AutomationTriggerSchema,
3
6
  AutomationTriggerStepId,
4
7
  } from "@budibase/types"
@@ -15,8 +18,8 @@ export const definition: AutomationTriggerSchema = {
15
18
  inputs: {
16
19
  properties: {
17
20
  tableId: {
18
- type: "string",
19
- customType: "table",
21
+ type: AutomationIOType.STRING,
22
+ customType: AutomationCustomIOType.TABLE,
20
23
  title: "Table",
21
24
  },
22
25
  },
@@ -25,21 +28,21 @@ export const definition: AutomationTriggerSchema = {
25
28
  outputs: {
26
29
  properties: {
27
30
  row: {
28
- type: "object",
29
- customType: "row",
31
+ type: AutomationIOType.OBJECT,
32
+ customType: AutomationCustomIOType.ROW,
30
33
  description: "The row that was updated",
31
34
  },
32
35
  id: {
33
- type: "string",
36
+ type: AutomationIOType.STRING,
34
37
  description: "Row ID - can be used for updating",
35
38
  },
36
39
  revision: {
37
- type: "string",
40
+ type: AutomationIOType.STRING,
38
41
  description: "Revision of row",
39
42
  },
40
43
  },
41
44
  required: ["row", "id"],
42
45
  },
43
46
  },
44
- type: "TRIGGER",
47
+ type: AutomationStepType.TRIGGER,
45
48
  }
@@ -1,4 +1,7 @@
1
1
  import {
2
+ AutomationCustomIOType,
3
+ AutomationIOType,
4
+ AutomationStepType,
2
5
  AutomationTriggerSchema,
3
6
  AutomationTriggerStepId,
4
7
  } from "@budibase/types"
@@ -15,13 +18,13 @@ export const definition: AutomationTriggerSchema = {
15
18
  inputs: {
16
19
  properties: {
17
20
  schemaUrl: {
18
- type: "string",
19
- customType: "webhookUrl",
21
+ type: AutomationIOType.STRING,
22
+ customType: AutomationCustomIOType.WEBHOOK_URL,
20
23
  title: "Schema URL",
21
24
  },
22
25
  triggerUrl: {
23
- type: "string",
24
- customType: "webhookUrl",
26
+ type: AutomationIOType.STRING,
27
+ customType: AutomationCustomIOType.WEBHOOK_URL,
25
28
  title: "Trigger URL",
26
29
  },
27
30
  },
@@ -30,12 +33,12 @@ export const definition: AutomationTriggerSchema = {
30
33
  outputs: {
31
34
  properties: {
32
35
  body: {
33
- type: "object",
36
+ type: AutomationIOType.OBJECT,
34
37
  description: "Body of the request which hit the webhook",
35
38
  },
36
39
  },
37
40
  required: ["body"],
38
41
  },
39
42
  },
40
- type: "TRIGGER",
43
+ type: AutomationStepType.TRIGGER,
41
44
  }
package/src/db/utils.ts CHANGED
@@ -27,6 +27,7 @@ export const isProdAppID = dbCore.isProdAppID
27
27
  export const USER_METDATA_PREFIX = `${DocumentType.ROW}${SEPARATOR}${dbCore.InternalTable.USER_METADATA}${SEPARATOR}`
28
28
  export const LINK_USER_METADATA_PREFIX = `${DocumentType.LINK}${SEPARATOR}${dbCore.InternalTable.USER_METADATA}${SEPARATOR}`
29
29
  export const TABLE_ROW_PREFIX = `${DocumentType.ROW}${SEPARATOR}${DocumentType.TABLE}`
30
+ export const AUTOMATION_LOG_PREFIX = `${DocumentType.AUTOMATION_LOG}${SEPARATOR}`
30
31
  export const ViewName = dbCore.ViewName
31
32
  export const InternalTables = dbCore.InternalTable
32
33
  export const UNICODE_MAX = dbCore.UNICODE_MAX
@@ -62,7 +62,6 @@ const environment = {
62
62
  // minor
63
63
  SALT_ROUNDS: process.env.SALT_ROUNDS,
64
64
  LOGGER: process.env.LOGGER,
65
- LOG_LEVEL: process.env.LOG_LEVEL,
66
65
  ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL,
67
66
  AUTOMATION_MAX_ITERATIONS:
68
67
  parseIntSafe(process.env.AUTOMATION_MAX_ITERATIONS) || 200,
@@ -0,0 +1 @@
1
+ export * from "./processors"
@@ -0,0 +1,14 @@
1
+ import userGroupProcessor from "./syncUsers"
2
+ import { docUpdates } from "@budibase/backend-core"
3
+
4
+ export type UpdateCallback = (docId: string) => void
5
+ let started = false
6
+
7
+ export function init(updateCb?: UpdateCallback) {
8
+ if (started) {
9
+ return
10
+ }
11
+ const processors = [userGroupProcessor(updateCb)]
12
+ docUpdates.init(processors)
13
+ started = true
14
+ }
@@ -0,0 +1,35 @@
1
+ import { constants, logging } from "@budibase/backend-core"
2
+ import { sdk as proSdk } from "@budibase/pro"
3
+ import { DocUpdateEvent, UserGroupSyncEvents } from "@budibase/types"
4
+ import { syncUsersToAllApps } from "../../sdk/app/applications/sync"
5
+ import { UpdateCallback } from "./processors"
6
+
7
+ export default function process(updateCb?: UpdateCallback) {
8
+ const processor = async (update: DocUpdateEvent) => {
9
+ try {
10
+ const docId = update.id
11
+ const isGroup = docId.startsWith(constants.DocumentType.GROUP)
12
+ let userIds: string[]
13
+ if (isGroup) {
14
+ const group = await proSdk.groups.get(docId)
15
+ userIds = group.users?.map(user => user._id) || []
16
+ } else {
17
+ userIds = [docId]
18
+ }
19
+ if (userIds.length > 0) {
20
+ await syncUsersToAllApps(userIds)
21
+ }
22
+ if (updateCb) {
23
+ updateCb(docId)
24
+ }
25
+ } catch (err: any) {
26
+ // if something not found - no changes to perform
27
+ if (err?.status === 404) {
28
+ return
29
+ } else {
30
+ logging.logAlert("Failed to perform user/group app sync", err)
31
+ }
32
+ }
33
+ }
34
+ return { events: UserGroupSyncEvents, processor }
35
+ }
@@ -2,4 +2,5 @@ import BudibaseEmitter from "./BudibaseEmitter"
2
2
 
3
3
  const emitter = new BudibaseEmitter()
4
4
 
5
+ export { init } from "./docUpdates"
5
6
  export default emitter
@@ -349,7 +349,7 @@ describe("row api - postgres", () => {
349
349
  },
350
350
  plus: true,
351
351
  source: "POSTGRES",
352
- type: "datasource",
352
+ type: "datasource_plus",
353
353
  _id: expect.any(String),
354
354
  _rev: expect.any(String),
355
355
  createdAt: expect.any(String),
@@ -921,6 +921,7 @@ describe("row api - postgres", () => {
921
921
  [m2mFieldName]: [
922
922
  {
923
923
  _id: row._id,
924
+ primaryDisplay: "Invalid display column",
924
925
  },
925
926
  ],
926
927
  })
@@ -929,6 +930,7 @@ describe("row api - postgres", () => {
929
930
  [m2mFieldName]: [
930
931
  {
931
932
  _id: row._id,
933
+ primaryDisplay: "Invalid display column",
932
934
  },
933
935
  ],
934
936
  })
@@ -79,10 +79,17 @@ function generateSchema(
79
79
  if (!relatedTable) {
80
80
  throw "Referenced table doesn't exist"
81
81
  }
82
- schema.integer(column.foreignKey).unsigned()
82
+ const relatedPrimary = relatedTable.primary[0]
83
+ const externalType = relatedTable.schema[relatedPrimary].externalType
84
+ if (externalType) {
85
+ schema.specificType(column.foreignKey, externalType)
86
+ } else {
87
+ schema.integer(column.foreignKey).unsigned()
88
+ }
89
+
83
90
  schema
84
91
  .foreign(column.foreignKey)
85
- .references(`${tableName}.${relatedTable.primary[0]}`)
92
+ .references(`${tableName}.${relatedPrimary}`)
86
93
  }
87
94
  break
88
95
  }
@@ -14,11 +14,11 @@ import firebase from "./firebase"
14
14
  import redis from "./redis"
15
15
  import snowflake from "./snowflake"
16
16
  import oracle from "./oracle"
17
- import { getPlugins } from "../api/controllers/plugin"
18
17
  import { SourceName, Integration, PluginType } from "@budibase/types"
19
18
  import { getDatasourcePlugin } from "../utilities/fileSystem"
20
19
  import env from "../environment"
21
20
  import { cloneDeep } from "lodash"
21
+ import sdk from "../sdk"
22
22
 
23
23
  const DEFINITIONS: { [key: string]: Integration } = {
24
24
  [SourceName.POSTGRES]: postgres.schema,
@@ -79,7 +79,7 @@ export async function getDefinition(source: SourceName): Promise<Integration> {
79
79
  export async function getDefinitions() {
80
80
  const pluginSchemas: { [key: string]: Integration } = {}
81
81
  if (env.SELF_HOSTED) {
82
- const plugins = await getPlugins(PluginType.DATASOURCE)
82
+ const plugins = await sdk.plugins.fetch(PluginType.DATASOURCE)
83
83
  // extract the actual schema from each custom
84
84
  for (let plugin of plugins) {
85
85
  const sourceId = plugin.name
@@ -103,7 +103,7 @@ export async function getIntegration(integration: string) {
103
103
  return INTEGRATIONS[integration]
104
104
  }
105
105
  if (env.SELF_HOSTED) {
106
- const plugins = await getPlugins(PluginType.DATASOURCE)
106
+ const plugins = await sdk.plugins.fetch(PluginType.DATASOURCE)
107
107
  for (let plugin of plugins) {
108
108
  if (plugin.name === integration) {
109
109
  // need to use commonJS require due to its dynamic runtime nature
@@ -243,11 +243,14 @@ class SqlServerIntegration extends Sql implements DatasourcePlus {
243
243
  if (typeof name !== "string") {
244
244
  continue
245
245
  }
246
+ const hasDefault = def.COLUMN_DEFAULT
247
+ const isAuto = !!autoColumns.find(col => col === name)
248
+ const required = !!requiredColumns.find(col => col === name)
246
249
  schema[name] = {
247
- autocolumn: !!autoColumns.find(col => col === name),
250
+ autocolumn: isAuto,
248
251
  name: name,
249
252
  constraints: {
250
- presence: requiredColumns.find(col => col === name),
253
+ presence: required && !isAuto && !hasDefault,
251
254
  },
252
255
  ...convertSqlType(def.DATA_TYPE),
253
256
  externalType: def.DATA_TYPE,
@@ -229,13 +229,15 @@ class MySQLIntegration extends Sql implements DatasourcePlus {
229
229
  if (column.Key === "PRI" && primaryKeys.indexOf(column.Key) === -1) {
230
230
  primaryKeys.push(columnName)
231
231
  }
232
- const constraints = {
233
- presence: column.Null !== "YES",
234
- }
232
+ const hasDefault = column.Default != null
235
233
  const isAuto: boolean =
236
234
  typeof column.Extra === "string" &&
237
235
  (column.Extra === "auto_increment" ||
238
236
  column.Extra.toLowerCase().includes("generated"))
237
+ const required = column.Null !== "YES"
238
+ const constraints = {
239
+ presence: required && !isAuto && !hasDefault,
240
+ }
239
241
  schema[columnName] = {
240
242
  name: columnName,
241
243
  autocolumn: isAuto,
@@ -262,15 +262,17 @@ class PostgresIntegration extends Sql implements DatasourcePlus {
262
262
  column.identity_start ||
263
263
  column.identity_increment
264
264
  )
265
- const constraints = {
266
- presence: column.is_nullable === "NO",
267
- }
268
- const hasDefault =
265
+ const hasDefault = column.column_default != null
266
+ const hasNextVal =
269
267
  typeof column.column_default === "string" &&
270
268
  column.column_default.startsWith("nextval")
271
269
  const isGenerated =
272
270
  column.is_generated && column.is_generated !== "NEVER"
273
- const isAuto: boolean = hasDefault || identity || isGenerated
271
+ const isAuto: boolean = hasNextVal || identity || isGenerated
272
+ const required = column.is_nullable === "NO"
273
+ const constraints = {
274
+ presence: required && !hasDefault && !isGenerated,
275
+ }
274
276
  tables[tableName].schema[columnName] = {
275
277
  autocolumn: isAuto,
276
278
  name: columnName,
@@ -6,6 +6,7 @@ interface RedisConfig {
6
6
  port: number
7
7
  username: string
8
8
  password?: string
9
+ db?: number
9
10
  }
10
11
 
11
12
  const SCHEMA: Integration = {
@@ -32,6 +33,12 @@ const SCHEMA: Integration = {
32
33
  type: "password",
33
34
  required: false,
34
35
  },
36
+ db: {
37
+ type: "number",
38
+ required: false,
39
+ display: "DB",
40
+ default: 0,
41
+ },
35
42
  },
36
43
  query: {
37
44
  create: {
@@ -88,6 +95,7 @@ class RedisIntegration {
88
95
  port: this.config.port,
89
96
  username: this.config.username,
90
97
  password: this.config.password,
98
+ db: this.config.db,
91
99
  })
92
100
  }
93
101
 
@@ -151,6 +151,9 @@ class RestIntegration implements IntegrationBase {
151
151
  data = data[keys[0]]
152
152
  }
153
153
  raw = rawXml
154
+ } else if (contentType.includes("application/pdf")) {
155
+ data = await response.arrayBuffer() // Save PDF as ArrayBuffer
156
+ raw = Buffer.from(data)
154
157
  } else {
155
158
  data = await response.text()
156
159
  raw = data
@@ -2,6 +2,7 @@ import { runQuotaMigration } from "./usageQuotas"
2
2
  import * as syncApps from "./usageQuotas/syncApps"
3
3
  import * as syncRows from "./usageQuotas/syncRows"
4
4
  import * as syncPlugins from "./usageQuotas/syncPlugins"
5
+ import * as syncUsers from "./usageQuotas/syncUsers"
5
6
 
6
7
  /**
7
8
  * Synchronise quotas to the state of the db.
@@ -11,5 +12,6 @@ export const run = async () => {
11
12
  await syncApps.run()
12
13
  await syncRows.run()
13
14
  await syncPlugins.run()
15
+ await syncUsers.run()
14
16
  })
15
17
  }
@@ -1,4 +1,4 @@
1
- import { tenancy, db as dbCore } from "@budibase/backend-core"
1
+ import { db as dbCore } from "@budibase/backend-core"
2
2
  import { quotas } from "@budibase/pro"
3
3
  import { QuotaUsageType, StaticQuotaName } from "@budibase/types"
4
4
 
@@ -8,7 +8,6 @@ export const run = async () => {
8
8
  const appCount = devApps ? devApps.length : 0
9
9
 
10
10
  // sync app count
11
- const tenantId = tenancy.getTenantId()
12
- console.log(`[Tenant: ${tenantId}] Syncing app count: ${appCount}`)
11
+ console.log(`Syncing app count: ${appCount}`)
13
12
  await quotas.setUsage(appCount, StaticQuotaName.APPS, QuotaUsageType.STATIC)
14
13
  }
@@ -1,4 +1,4 @@
1
- import { tenancy, db as dbCore } from "@budibase/backend-core"
1
+ import { db as dbCore } from "@budibase/backend-core"
2
2
  import { getUniqueRows } from "../../../utilities/usageQuota/rows"
3
3
  import { quotas } from "@budibase/pro"
4
4
  import { StaticQuotaName, QuotaUsageType, App } from "@budibase/types"
@@ -18,8 +18,7 @@ export const run = async () => {
18
18
  })
19
19
 
20
20
  // sync row count
21
- const tenantId = tenancy.getTenantId()
22
- console.log(`[Tenant: ${tenantId}] Syncing row count: ${rowCount}`)
21
+ console.log(`Syncing row count: ${rowCount}`)
23
22
  await quotas.setUsagePerApp(
24
23
  counts,
25
24
  StaticQuotaName.ROWS,
@@ -0,0 +1,9 @@
1
+ import { users } from "@budibase/backend-core"
2
+ import { quotas } from "@budibase/pro"
3
+ import { QuotaUsageType, StaticQuotaName } from "@budibase/types"
4
+
5
+ export const run = async () => {
6
+ const userCount = await users.getUserCount()
7
+ console.log(`Syncing user count: ${userCount}`)
8
+ await quotas.setUsage(userCount, StaticQuotaName.USERS, QuotaUsageType.STATIC)
9
+ }
@@ -24,7 +24,7 @@ describe("syncRows", () => {
24
24
 
25
25
  // app 1
26
26
  const app1 = config.app
27
- await context.doInAppContext(app1.appId, async () => {
27
+ await context.doInAppContext(app1!.appId, async () => {
28
28
  await config.createTable()
29
29
  await config.createRow()
30
30
  })
@@ -43,7 +43,7 @@ describe("syncRows", () => {
43
43
  usageDoc = await quotas.getQuotaUsage()
44
44
  expect(usageDoc.usageQuota.rows).toEqual(3)
45
45
  expect(
46
- usageDoc.apps?.[dbCore.getProdAppID(app1.appId)].usageQuota.rows
46
+ usageDoc.apps?.[dbCore.getProdAppID(app1!.appId)].usageQuota.rows
47
47
  ).toEqual(1)
48
48
  expect(
49
49
  usageDoc.apps?.[dbCore.getProdAppID(app2.appId)].usageQuota.rows
@@ -0,0 +1,26 @@
1
+ import TestConfig from "../../../../tests/utilities/TestConfiguration"
2
+ import * as syncUsers from "../syncUsers"
3
+ import { quotas } from "@budibase/pro"
4
+
5
+ describe("syncUsers", () => {
6
+ let config = new TestConfig(false)
7
+
8
+ beforeEach(async () => {
9
+ await config.init()
10
+ })
11
+
12
+ afterAll(config.end)
13
+
14
+ it("syncs users", async () => {
15
+ return config.doInContext(null, async () => {
16
+ await config.createUser()
17
+
18
+ await syncUsers.run()
19
+
20
+ const usageDoc = await quotas.getQuotaUsage()
21
+ // default + additional user
22
+ const userCount = 2
23
+ expect(usageDoc.usageQuota.users).toBe(userCount)
24
+ })
25
+ })
26
+ })
@@ -11,6 +11,7 @@ import env from "../environment"
11
11
  // migration functions
12
12
  import * as userEmailViewCasing from "./functions/userEmailViewCasing"
13
13
  import * as syncQuotas from "./functions/syncQuotas"
14
+ import * as syncUsers from "./functions/usageQuotas/syncUsers"
14
15
  import * as appUrls from "./functions/appUrls"
15
16
  import * as tableSettings from "./functions/tableSettings"
16
17
  import * as backfill from "./functions/backfill"