@budibase/server 1.0.21 → 1.0.23-alpha.2

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 (238) hide show
  1. package/__mocks__/node-fetch.ts +3 -0
  2. package/builder/assets/bb-spaceship.8f6e81e1.svg +227 -0
  3. package/builder/assets/{index.c2e9e4e2.js → index.26923a83.js} +208 -204
  4. package/builder/assets/{index.4fb3f887.css → index.4a13c4cb.css} +1 -1
  5. package/builder/assets/{vendor.470042a4.js → vendor.f9faf6ab.js} +88 -88
  6. package/builder/index.html +3 -3
  7. package/coverage/clover.xml +654 -567
  8. package/coverage/coverage-final.json +22 -20
  9. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/application.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/automation.js.html +22 -10
  14. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/datasource.js.html +14 -14
  18. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/hosting.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/index.html +28 -43
  21. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/query/index.html +126 -0
  26. package/coverage/lcov-report/api/controllers/{query.js.html → query/index.js.html} +159 -27
  27. package/coverage/lcov-report/api/controllers/query/validation.js.html +203 -0
  28. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  32. package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  40. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/table/internal.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/table/utils.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/user.js.html +108 -9
  45. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  46. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  47. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  48. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  49. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  50. package/coverage/lcov-report/api/controllers/webhook.js.html +18 -6
  51. package/coverage/lcov-report/api/index.html +1 -1
  52. package/coverage/lcov-report/api/index.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/index.html +9 -9
  66. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/query.js.html +11 -98
  72. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/static.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/user.js.html +32 -2
  81. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  82. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  83. package/coverage/lcov-report/automations/actions.js.html +1 -1
  84. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  85. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  86. package/coverage/lcov-report/automations/index.html +20 -20
  87. package/coverage/lcov-report/automations/index.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/index.html +1 -1
  97. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  98. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +5 -8
  99. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  100. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  101. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  102. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  103. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  104. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  105. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  106. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  107. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  108. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  109. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  110. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  111. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  112. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  113. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  114. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  115. package/coverage/lcov-report/automations/utils.js.html +44 -11
  116. package/coverage/lcov-report/constants/index.html +1 -1
  117. package/coverage/lcov-report/constants/index.js.html +22 -22
  118. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  119. package/coverage/lcov-report/constants/screens.js.html +1 -1
  120. package/coverage/lcov-report/db/client.js.html +18 -18
  121. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  122. package/coverage/lcov-report/db/index.html +15 -15
  123. package/coverage/lcov-report/db/index.js.html +3 -3
  124. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  125. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  126. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  127. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  128. package/coverage/lcov-report/db/newid.js.html +4 -4
  129. package/coverage/lcov-report/db/utils.js.html +91 -64
  130. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  131. package/coverage/lcov-report/events/index.html +1 -1
  132. package/coverage/lcov-report/events/index.js.html +1 -1
  133. package/coverage/lcov-report/events/utils.js.html +1 -1
  134. package/coverage/lcov-report/index.html +76 -61
  135. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  136. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  137. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  138. package/coverage/lcov-report/middleware/authorized.js.html +2 -2
  139. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  140. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  141. package/coverage/lcov-report/middleware/index.html +1 -1
  142. package/coverage/lcov-report/middleware/joi-validator.js.html +3 -3
  143. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  144. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  145. package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
  146. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  147. package/coverage/lcov-report/threads/automation.js.html +3 -6
  148. package/coverage/lcov-report/threads/index.html +35 -20
  149. package/coverage/lcov-report/threads/index.js.html +1 -1
  150. package/coverage/lcov-report/threads/query.js.html +62 -17
  151. package/coverage/lcov-report/threads/utils.js.html +119 -0
  152. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  153. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  154. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  155. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  156. package/coverage/lcov-report/utilities/global.js.html +1 -1
  157. package/coverage/lcov-report/utilities/index.html +19 -19
  158. package/coverage/lcov-report/utilities/index.js.html +66 -33
  159. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  160. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  161. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  162. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  163. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  164. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  165. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  166. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  167. package/coverage/lcov-report/utilities/security.js.html +2 -2
  168. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  169. package/coverage/lcov-report/utilities/users.js.html +1 -1
  170. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  171. package/coverage/lcov.info +1058 -918
  172. package/dist/api/controllers/automation.js +7 -5
  173. package/dist/api/controllers/query/import/index.js +79 -0
  174. package/dist/api/controllers/query/import/sources/base/index.js +63 -0
  175. package/dist/api/controllers/query/import/sources/base/openapi.js +42 -0
  176. package/dist/api/controllers/query/import/sources/curl.js +90 -0
  177. package/dist/api/controllers/query/import/sources/openapi2.js +139 -0
  178. package/dist/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
  179. package/dist/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
  180. package/dist/api/controllers/{query.js → query/index.js} +42 -6
  181. package/dist/api/controllers/query/validation.js +37 -0
  182. package/dist/api/controllers/user.js +37 -1
  183. package/dist/api/controllers/webhook.js +4 -0
  184. package/dist/api/routes/query.js +2 -32
  185. package/dist/api/routes/user.js +3 -1
  186. package/dist/automations/steps/outgoingWebhook.js +2 -3
  187. package/dist/automations/utils.js +10 -0
  188. package/dist/db/utils.js +8 -0
  189. package/dist/definitions/datasource.js +6 -1
  190. package/dist/integrations/rest.js +207 -117
  191. package/dist/package.json +10 -4
  192. package/dist/threads/automation.js +1 -2
  193. package/dist/threads/query.js +15 -5
  194. package/dist/threads/utils.js +13 -0
  195. package/dist/tsconfig.tsbuildinfo +1 -1
  196. package/dist/utilities/index.js +10 -0
  197. package/package.json +11 -5
  198. package/src/api/controllers/automation.js +8 -4
  199. package/src/api/controllers/query/import/index.ts +85 -0
  200. package/src/api/controllers/query/import/sources/base/index.ts +85 -0
  201. package/src/api/controllers/query/import/sources/base/openapi.ts +24 -0
  202. package/src/api/controllers/query/import/sources/curl.ts +94 -0
  203. package/src/api/controllers/query/import/sources/openapi2.ts +159 -0
  204. package/src/api/controllers/query/import/sources/tests/curl/curl.spec.js +104 -0
  205. package/src/api/controllers/query/import/sources/tests/curl/data/delete.txt +1 -0
  206. package/src/api/controllers/query/import/sources/tests/curl/data/empty-body.txt +2 -0
  207. package/src/api/controllers/query/import/sources/tests/curl/data/get.txt +1 -0
  208. package/src/api/controllers/query/import/sources/tests/curl/data/headers.txt +3 -0
  209. package/src/api/controllers/query/import/sources/tests/curl/data/patch.txt +2 -0
  210. package/src/api/controllers/query/import/sources/tests/curl/data/path.txt +1 -0
  211. package/src/api/controllers/query/import/sources/tests/curl/data/post.txt +2 -0
  212. package/src/api/controllers/query/import/sources/tests/curl/data/put.txt +2 -0
  213. package/src/api/controllers/query/import/sources/tests/curl/data/query.txt +1 -0
  214. package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
  215. package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.yaml +160 -0
  216. package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
  217. package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.yaml +711 -0
  218. package/src/api/controllers/query/import/sources/tests/openapi2/openapi2.spec.js +239 -0
  219. package/src/api/controllers/query/import/tests/index.spec.js +115 -0
  220. package/src/api/controllers/{query.js → query/index.js} +50 -6
  221. package/src/api/controllers/query/validation.js +41 -0
  222. package/src/api/controllers/user.js +33 -0
  223. package/src/api/controllers/webhook.js +4 -0
  224. package/src/api/routes/query.js +5 -34
  225. package/src/api/routes/user.js +10 -0
  226. package/src/automations/steps/outgoingWebhook.js +2 -3
  227. package/src/automations/utils.js +11 -0
  228. package/src/db/utils.js +9 -0
  229. package/src/definitions/common.ts +2 -16
  230. package/src/definitions/datasource.ts +73 -1
  231. package/src/integrations/base/IntegrationBase.ts +4 -4
  232. package/src/integrations/oracle.ts +1 -1
  233. package/src/integrations/rest.ts +227 -137
  234. package/src/integrations/tests/rest.spec.js +167 -19
  235. package/src/threads/automation.js +1 -2
  236. package/src/threads/query.js +20 -5
  237. package/src/threads/utils.js +13 -0
  238. package/src/utilities/index.js +11 -0
@@ -0,0 +1,239 @@
1
+ const { OpenAPI2 } = require("../../openapi2")
2
+ const fs = require("fs")
3
+ const path = require('path')
4
+
5
+ const getData = (file, extension) => {
6
+ return fs.readFileSync(path.join(__dirname, `./data/${file}/${file}.${extension}`), "utf8")
7
+ }
8
+
9
+ describe("OpenAPI2 Import", () => {
10
+ let openapi2
11
+
12
+ beforeEach(() => {
13
+ openapi2 = new OpenAPI2()
14
+ })
15
+
16
+ it("validates unsupported data", async () => {
17
+ let data
18
+ let supported
19
+
20
+ // non json / yaml
21
+ data = "curl http://example.com"
22
+ supported = await openapi2.isSupported(data)
23
+ expect(supported).toBe(false)
24
+
25
+ // Empty
26
+ data = ""
27
+ supported = await openapi2.isSupported(data)
28
+ expect(supported).toBe(false)
29
+ })
30
+
31
+ const init = async (file, extension) => {
32
+ await openapi2.isSupported(getData(file, extension))
33
+ }
34
+
35
+ const runTests = async (filename, test, assertions) => {
36
+ for (let extension of ["json", "yaml"]) {
37
+ await test(filename, extension, assertions)
38
+ }
39
+ }
40
+
41
+ const testImportInfo = async (file, extension) => {
42
+ await init(file, extension)
43
+ const info = await openapi2.getInfo()
44
+ expect(info.url).toBe("https://petstore.swagger.io/v2")
45
+ expect(info.name).toBe("Swagger Petstore")
46
+ }
47
+
48
+ it("returns import info", async () => {
49
+ await runTests("petstore", testImportInfo)
50
+ })
51
+
52
+ describe("Returns queries", () => {
53
+ const indexQueries = (queries) => {
54
+ return queries.reduce((acc, query) => {
55
+ acc[query.name] = query
56
+ return acc
57
+ }, {})
58
+ }
59
+
60
+ const getQueries = async (file, extension) => {
61
+ await init(file, extension)
62
+ const queries = await openapi2.getQueries()
63
+ expect(queries.length).toBe(6)
64
+ return indexQueries(queries)
65
+ }
66
+
67
+ const testVerb = async (file, extension, assertions) => {
68
+ const queries = await getQueries(file, extension)
69
+ for (let [operationId, method] of Object.entries(assertions)) {
70
+ expect(queries[operationId].queryVerb).toBe(method)
71
+ }
72
+ }
73
+
74
+ it("populates verb", async () => {
75
+ const assertions = {
76
+ "createEntity" : "create",
77
+ "getEntities" : "read",
78
+ "getEntity" : "read",
79
+ "updateEntity" : "update",
80
+ "patchEntity" : "patch",
81
+ "deleteEntity" : "delete"
82
+ }
83
+ await runTests("crud", testVerb, assertions)
84
+ })
85
+
86
+ const testPath = async (file, extension, assertions) => {
87
+ const queries = await getQueries(file, extension)
88
+ for (let [operationId, urlPath] of Object.entries(assertions)) {
89
+ expect(queries[operationId].fields.path).toBe(urlPath)
90
+ }
91
+ }
92
+
93
+ it("populates path", async () => {
94
+ const assertions = {
95
+ "createEntity" : "entities",
96
+ "getEntities" : "entities",
97
+ "getEntity" : "entities/{{entityId}}",
98
+ "updateEntity" : "entities/{{entityId}}",
99
+ "patchEntity" : "entities/{{entityId}}",
100
+ "deleteEntity" : "entities/{{entityId}}"
101
+ }
102
+ await runTests("crud", testPath, assertions)
103
+ })
104
+
105
+ const testHeaders = async (file, extension, assertions) => {
106
+ const queries = await getQueries(file, extension)
107
+ for (let [operationId, headers] of Object.entries(assertions)) {
108
+ expect(queries[operationId].fields.headers).toStrictEqual(headers)
109
+ }
110
+ }
111
+
112
+ const contentTypeHeader = {
113
+ "Content-Type" : "application/json",
114
+ }
115
+
116
+ it("populates headers", async () => {
117
+ const assertions = {
118
+ "createEntity" : {
119
+ ...contentTypeHeader
120
+ },
121
+ "getEntities" : {
122
+ },
123
+ "getEntity" : {
124
+ },
125
+ "updateEntity" : {
126
+ ...contentTypeHeader
127
+ },
128
+ "patchEntity" : {
129
+ ...contentTypeHeader
130
+ },
131
+ "deleteEntity" : {
132
+ "x-api-key" : "{{x-api-key}}",
133
+ }
134
+ }
135
+
136
+ await runTests("crud", testHeaders, assertions)
137
+ })
138
+
139
+ const testQuery = async (file, extension, assertions) => {
140
+ const queries = await getQueries(file, extension)
141
+ for (let [operationId, queryString] of Object.entries(assertions)) {
142
+ expect(queries[operationId].fields.queryString).toStrictEqual(queryString)
143
+ }
144
+ }
145
+
146
+ it("populates query", async () => {
147
+ const assertions = {
148
+ "createEntity" : "",
149
+ "getEntities" : "page={{page}}&size={{size}}",
150
+ "getEntity" : "",
151
+ "updateEntity" : "",
152
+ "patchEntity" : "",
153
+ "deleteEntity" : ""
154
+ }
155
+ await runTests("crud", testQuery, assertions)
156
+ })
157
+
158
+ const testParameters = async (file, extension, assertions) => {
159
+ const queries = await getQueries(file, extension)
160
+ for (let [operationId, parameters] of Object.entries(assertions)) {
161
+ expect(queries[operationId].parameters).toStrictEqual(parameters)
162
+ }
163
+ }
164
+
165
+ it("populates parameters", async () => {
166
+ const assertions = {
167
+ "createEntity" : [],
168
+ "getEntities" : [
169
+ {
170
+ "name" : "page",
171
+ "default" : "",
172
+ },
173
+ {
174
+ "name" : "size",
175
+ "default" : "",
176
+ }
177
+ ],
178
+ "getEntity" : [
179
+ {
180
+ "name" : "entityId",
181
+ "default" : "",
182
+ }
183
+ ],
184
+ "updateEntity" : [
185
+ {
186
+ "name" : "entityId",
187
+ "default" : "",
188
+ }
189
+ ],
190
+ "patchEntity" : [
191
+ {
192
+ "name" : "entityId",
193
+ "default" : "",
194
+ }
195
+ ],
196
+ "deleteEntity" : [
197
+ {
198
+ "name" : "entityId",
199
+ "default" : "",
200
+ },
201
+ {
202
+ "name" : "x-api-key",
203
+ "default" : "",
204
+ }
205
+ ]
206
+ }
207
+ await runTests("crud", testParameters, assertions)
208
+ })
209
+
210
+ const testBody = async (file, extension, assertions) => {
211
+ const queries = await getQueries(file, extension)
212
+ for (let [operationId, body] of Object.entries(assertions)) {
213
+ expect(queries[operationId].fields.requestBody).toStrictEqual(JSON.stringify(body, null, 2))
214
+ }
215
+ }
216
+ it("populates body", async () => {
217
+ const assertions = {
218
+ "createEntity" : {
219
+ "name" : "name",
220
+ "type" : "type",
221
+ },
222
+ "getEntities" : undefined,
223
+ "getEntity" : undefined,
224
+ "updateEntity" : {
225
+ "id": 1,
226
+ "name" : "name",
227
+ "type" : "type",
228
+ },
229
+ "patchEntity" : {
230
+ "id": 1,
231
+ "name" : "name",
232
+ "type" : "type",
233
+ },
234
+ "deleteEntity" : undefined
235
+ }
236
+ await runTests("crud", testBody, assertions)
237
+ })
238
+ })
239
+ })
@@ -0,0 +1,115 @@
1
+
2
+ const bulkDocs = jest.fn()
3
+ const db = jest.fn(() => {
4
+ return {
5
+ bulkDocs
6
+ }
7
+ })
8
+ jest.mock("../../../../../db", () => db)
9
+
10
+ const { RestImporter } = require("../index")
11
+
12
+ const fs = require("fs")
13
+ const path = require('path')
14
+
15
+ const getData = (file) => {
16
+ return fs.readFileSync(path.join(__dirname, `../sources/tests/${file}`), "utf8")
17
+ }
18
+
19
+ // openapi2 (swagger)
20
+ const oapi2CrudJson = getData("openapi2/data/crud/crud.json")
21
+ const oapi2CrudYaml = getData("openapi2/data/crud/crud.json")
22
+ const oapi2PetstoreJson = getData("openapi2/data/petstore/petstore.json")
23
+ const oapi2PetstoreYaml = getData("openapi2/data/petstore/petstore.json")
24
+
25
+ // curl
26
+ const curl = getData("curl/data/post.txt")
27
+
28
+ const datasets = {
29
+ oapi2CrudJson,
30
+ oapi2CrudYaml,
31
+ oapi2PetstoreJson,
32
+ oapi2PetstoreYaml,
33
+ curl
34
+ }
35
+
36
+ describe("Rest Importer", () => {
37
+ let restImporter
38
+
39
+ const init = async (data) => {
40
+ restImporter = new RestImporter(data)
41
+ await restImporter.init()
42
+ }
43
+
44
+ const runTest = async (test, assertions) => {
45
+ for (let [key, data] of Object.entries(datasets)) {
46
+ await test(key, data, assertions)
47
+ }
48
+ }
49
+
50
+ const testGetInfo = async (key, data, assertions) => {
51
+ await init(data)
52
+ const info = await restImporter.getInfo()
53
+ expect(info.name).toBe(assertions[key].name)
54
+ expect(info.url).toBe(assertions[key].url)
55
+ }
56
+
57
+ it("gets info", async () => {
58
+ const assertions = {
59
+ "oapi2CrudJson" : {
60
+ name: "CRUD",
61
+ url: "http://example.com"
62
+ },
63
+ "oapi2CrudYaml" : {
64
+ name: "CRUD",
65
+ url: "http://example.com"
66
+ },
67
+ "oapi2PetstoreJson" : {
68
+ name: "Swagger Petstore",
69
+ url: "https://petstore.swagger.io/v2"
70
+ },
71
+ "oapi2PetstoreYaml" :{
72
+ name: "Swagger Petstore",
73
+ url: "https://petstore.swagger.io/v2"
74
+ },
75
+ "curl": {
76
+ name: "example.com",
77
+ url: "http://example.com"
78
+ }
79
+ }
80
+ await runTest(testGetInfo, assertions)
81
+ })
82
+
83
+ const testImportQueries = async (key, data, assertions) => {
84
+ await init(data)
85
+ bulkDocs.mockReturnValue([])
86
+ const importResult = await restImporter.importQueries("appId", "datasourceId")
87
+ expect(importResult.errorQueries.length).toBe(0)
88
+ expect(importResult.queries.length).toBe(assertions[key].count)
89
+ expect(bulkDocs).toHaveBeenCalledTimes(1)
90
+ jest.clearAllMocks()
91
+ }
92
+
93
+ it("imports queries", async () => {
94
+ // simple sanity assertions that the whole dataset
95
+ // makes it through the importer
96
+ const assertions = {
97
+ "oapi2CrudJson" : {
98
+ count: 6,
99
+ },
100
+ "oapi2CrudYaml" :{
101
+ count: 6,
102
+ },
103
+ "oapi2PetstoreJson" : {
104
+ count: 20,
105
+ },
106
+ "oapi2PetstoreYaml" :{
107
+ count: 20,
108
+ },
109
+ "curl": {
110
+ count: 1
111
+ }
112
+ }
113
+ await runTest(testImportQueries, assertions)
114
+ })
115
+ })
@@ -1,12 +1,14 @@
1
1
  const { processString } = require("@budibase/string-templates")
2
- const CouchDB = require("../../db")
2
+ const CouchDB = require("../../../db")
3
3
  const {
4
4
  generateQueryID,
5
5
  getQueryParams,
6
6
  isProdAppID,
7
- } = require("../../db/utils")
8
- const { BaseQueryVerbs } = require("../../constants")
9
- const { Thread, ThreadType } = require("../../threads")
7
+ } = require("../../../db/utils")
8
+ const { BaseQueryVerbs } = require("../../../constants")
9
+ const { Thread, ThreadType } = require("../../../threads")
10
+ const { save: saveDatasource } = require("../datasource")
11
+ const { RestImporter } = require("./import")
10
12
 
11
13
  const Runner = new Thread(ThreadType.QUERY, { timeoutMs: 10000 })
12
14
 
@@ -30,9 +32,49 @@ exports.fetch = async function (ctx) {
30
32
  include_docs: true,
31
33
  })
32
34
  )
35
+
33
36
  ctx.body = enrichQueries(body.rows.map(row => row.doc))
34
37
  }
35
38
 
39
+ exports.import = async ctx => {
40
+ const body = ctx.request.body
41
+ const data = body.data
42
+
43
+ const importer = new RestImporter(data)
44
+ await importer.init()
45
+
46
+ let datasourceId
47
+ if (!body.datasourceId) {
48
+ // construct new datasource
49
+ const info = await importer.getInfo()
50
+ let datasource = {
51
+ type: "datasource",
52
+ source: "REST",
53
+ config: {
54
+ url: info.url,
55
+ defaultHeaders: [],
56
+ },
57
+ name: info.name,
58
+ }
59
+ // save the datasource
60
+ const datasourceCtx = { ...ctx }
61
+ datasourceCtx.request.body.datasource = datasource
62
+ await saveDatasource(datasourceCtx)
63
+ datasourceId = datasourceCtx.body.datasource._id
64
+ } else {
65
+ // use existing datasource
66
+ datasourceId = body.datasourceId
67
+ }
68
+
69
+ const importResult = await importer.importQueries(ctx.appId, datasourceId)
70
+
71
+ ctx.body = {
72
+ ...importResult,
73
+ datasourceId,
74
+ }
75
+ ctx.status = 200
76
+ }
77
+
36
78
  exports.save = async function (ctx) {
37
79
  const db = new CouchDB(ctx.appId)
38
80
  const query = ctx.request.body
@@ -81,7 +123,7 @@ async function enrichQueryFields(fields, parameters = {}) {
81
123
  enrichedQuery.requestBody
82
124
  )
83
125
  } catch (err) {
84
- throw { message: `JSON Invalid - error: ${err}` }
126
+ // no json found, ignore
85
127
  }
86
128
  delete enrichedQuery.customData
87
129
  }
@@ -109,7 +151,7 @@ exports.preview = async function (ctx) {
109
151
  const enrichedQuery = await enrichQueryFields(fields, parameters)
110
152
 
111
153
  try {
112
- const { rows, keys } = await Runner.run({
154
+ const { rows, keys, info, extra } = await Runner.run({
113
155
  datasource,
114
156
  queryVerb,
115
157
  query: enrichedQuery,
@@ -119,6 +161,8 @@ exports.preview = async function (ctx) {
119
161
  ctx.body = {
120
162
  rows,
121
163
  schemaFields: [...new Set(keys)],
164
+ info,
165
+ extra,
122
166
  }
123
167
  } catch (err) {
124
168
  ctx.throw(400, err)
@@ -0,0 +1,41 @@
1
+ const joiValidator = require("../../../middleware/joi-validator")
2
+ const Joi = require("joi")
3
+
4
+ exports.queryValidation = () => {
5
+ return Joi.object({
6
+ _id: Joi.string(),
7
+ _rev: Joi.string(),
8
+ name: Joi.string().required(),
9
+ fields: Joi.object().required(),
10
+ datasourceId: Joi.string().required(),
11
+ readable: Joi.boolean(),
12
+ parameters: Joi.array().items(
13
+ Joi.object({
14
+ name: Joi.string(),
15
+ default: Joi.string().allow(""),
16
+ })
17
+ ),
18
+ queryVerb: Joi.string().allow().required(),
19
+ extra: Joi.object().optional(),
20
+ schema: Joi.object({}).required().unknown(true),
21
+ transformer: Joi.string().optional(),
22
+ flags: Joi.object().optional(),
23
+ })
24
+ }
25
+
26
+ exports.generateQueryValidation = () => {
27
+ // prettier-ignore
28
+ return joiValidator.body(exports.queryValidation())
29
+ }
30
+
31
+ exports.generateQueryPreviewValidation = () => {
32
+ // prettier-ignore
33
+ return joiValidator.body(Joi.object({
34
+ fields: Joi.object().required(),
35
+ queryVerb: Joi.string().allow().required(),
36
+ extra: Joi.object().optional(),
37
+ datasourceId: Joi.string().required(),
38
+ transformer: Joi.string().optional(),
39
+ parameters: Joi.object({}).required().unknown(true)
40
+ }))
41
+ }
@@ -2,6 +2,7 @@ const CouchDB = require("../../db")
2
2
  const {
3
3
  generateUserMetadataID,
4
4
  getUserMetadataParams,
5
+ generateUserFlagID,
5
6
  } = require("../../db/utils")
6
7
  const { InternalTables } = require("../../db/utils")
7
8
  const { getGlobalUsers, getRawGlobalUser } = require("../../utilities/global")
@@ -195,3 +196,35 @@ exports.destroyMetadata = async function (ctx) {
195
196
  exports.findMetadata = async function (ctx) {
196
197
  ctx.body = await getFullUser(ctx, ctx.params.id)
197
198
  }
199
+
200
+ exports.setFlag = async function (ctx) {
201
+ const userId = ctx.user._id
202
+ const { flag, value } = ctx.request.body
203
+ if (!flag) {
204
+ ctx.throw(400, "Must supply a 'flag' field in request body.")
205
+ }
206
+ const flagDocId = generateUserFlagID(userId)
207
+ const db = new CouchDB(ctx.appId)
208
+ let doc
209
+ try {
210
+ doc = await db.get(flagDocId)
211
+ } catch (err) {
212
+ doc = { _id: flagDocId }
213
+ }
214
+ doc[flag] = value || true
215
+ await db.put(doc)
216
+ ctx.body = { message: "Flag set successfully" }
217
+ }
218
+
219
+ exports.getFlags = async function (ctx) {
220
+ const userId = ctx.user._id
221
+ const docId = generateUserFlagID(userId)
222
+ const db = new CouchDB(ctx.appId)
223
+ let doc
224
+ try {
225
+ doc = await db.get(docId)
226
+ } catch (err) {
227
+ doc = { _id: docId }
228
+ }
229
+ ctx.body = doc
230
+ }
@@ -65,6 +65,10 @@ exports.buildSchema = async ctx => {
65
65
  let automation = await db.get(webhook.action.target)
66
66
  const autoOutputs = automation.definition.trigger.schema.outputs
67
67
  let properties = webhook.bodySchema.properties
68
+ // reset webhook outputs
69
+ autoOutputs.properties = {
70
+ body: autoOutputs.properties.body,
71
+ }
68
72
  for (let prop of Object.keys(properties)) {
69
73
  autoOutputs.properties[prop] = {
70
74
  type: properties[prop].type,
@@ -1,53 +1,23 @@
1
1
  const Router = require("@koa/router")
2
2
  const queryController = require("../controllers/query")
3
3
  const authorized = require("../../middleware/authorized")
4
- const Joi = require("joi")
5
4
  const {
6
5
  PermissionLevels,
7
6
  PermissionTypes,
8
7
  BUILDER,
9
8
  } = require("@budibase/auth/permissions")
10
- const joiValidator = require("../../middleware/joi-validator")
11
9
  const {
12
10
  bodyResource,
13
11
  bodySubResource,
14
12
  paramResource,
15
13
  } = require("../../middleware/resourceId")
14
+ const {
15
+ generateQueryPreviewValidation,
16
+ generateQueryValidation,
17
+ } = require("../controllers/query/validation")
16
18
 
17
19
  const router = Router()
18
20
 
19
- function generateQueryValidation() {
20
- // prettier-ignore
21
- return joiValidator.body(Joi.object({
22
- _id: Joi.string(),
23
- _rev: Joi.string(),
24
- name: Joi.string().required(),
25
- fields: Joi.object().required(),
26
- datasourceId: Joi.string().required(),
27
- readable: Joi.boolean(),
28
- parameters: Joi.array().items(Joi.object({
29
- name: Joi.string(),
30
- default: Joi.string().allow(""),
31
- })),
32
- queryVerb: Joi.string().allow().required(),
33
- extra: Joi.object().optional(),
34
- schema: Joi.object({}).required().unknown(true),
35
- transformer: Joi.string().optional(),
36
- }))
37
- }
38
-
39
- function generateQueryPreviewValidation() {
40
- // prettier-ignore
41
- return joiValidator.body(Joi.object({
42
- fields: Joi.object().required(),
43
- queryVerb: Joi.string().allow().required(),
44
- extra: Joi.object().optional(),
45
- datasourceId: Joi.string().required(),
46
- transformer: Joi.string().optional(),
47
- parameters: Joi.object({}).required().unknown(true)
48
- }))
49
- }
50
-
51
21
  router
52
22
  .get("/api/queries", authorized(BUILDER), queryController.fetch)
53
23
  .post(
@@ -57,6 +27,7 @@ router
57
27
  generateQueryValidation(),
58
28
  queryController.save
59
29
  )
30
+ .post("/api/queries/import", authorized(BUILDER), queryController.import)
60
31
  .post(
61
32
  "/api/queries/preview",
62
33
  bodyResource("datasourceId"),
@@ -39,5 +39,15 @@ router
39
39
  authorized(PermissionTypes.USER, PermissionLevels.WRITE),
40
40
  controller.syncUser
41
41
  )
42
+ .post(
43
+ "/api/users/flags",
44
+ authorized(PermissionTypes.USER, PermissionLevels.WRITE),
45
+ controller.setFlag
46
+ )
47
+ .get(
48
+ "/api/users/flags",
49
+ authorized(PermissionTypes.USER, PermissionLevels.READ),
50
+ controller.getFlags
51
+ )
42
52
 
43
53
  module.exports = router
@@ -13,12 +13,11 @@ const RequestType = {
13
13
  const BODY_REQUESTS = [RequestType.POST, RequestType.PUT, RequestType.PATCH]
14
14
 
15
15
  /**
16
- * Note, there is some functionality in this that is not currently exposed as it
17
- * is complex and maybe better to be opinionated here.
18
- * GET/DELETE requests cannot handle body elements so they will not be sent if configured.
16
+ * NOTE: this functionality is deprecated - it no longer should be used.
19
17
  */
20
18
 
21
19
  exports.definition = {
20
+ deprecated: true,
22
21
  name: "Outgoing webhook",
23
22
  tagline: "Send a {{inputs.requestMethod}} request",
24
23
  icon: "Send",
@@ -7,6 +7,7 @@ const newid = require("../db/newid")
7
7
  const { updateEntityMetadata } = require("../utilities")
8
8
  const { MetadataTypes } = require("../constants")
9
9
  const { getDeployedAppID } = require("@budibase/auth/db")
10
+ const { cloneDeep } = require("lodash/fp")
10
11
 
11
12
  const WH_STEP_ID = definitions.WEBHOOK.stepId
12
13
  const CRON_STEP_ID = definitions.CRON.stepId
@@ -42,6 +43,16 @@ exports.updateTestHistory = async (appId, automation, history) => {
42
43
  )
43
44
  }
44
45
 
46
+ exports.removeDeprecated = definitions => {
47
+ const base = cloneDeep(definitions)
48
+ for (let key of Object.keys(base)) {
49
+ if (base[key].deprecated) {
50
+ delete base[key]
51
+ }
52
+ }
53
+ return base
54
+ }
55
+
45
56
  // end the repetition and the job itself
46
57
  exports.disableAllCrons = async appId => {
47
58
  const promises = []
package/src/db/utils.js CHANGED
@@ -40,6 +40,7 @@ const DocumentTypes = {
40
40
  DEPLOYMENTS: "deployments",
41
41
  METADATA: "metadata",
42
42
  MEM_VIEW: "view",
43
+ USER_FLAG: "flag",
43
44
  }
44
45
 
45
46
  const ViewNames = {
@@ -339,6 +340,14 @@ exports.getQueryParams = (datasourceId = null, otherProps = {}) => {
339
340
  )
340
341
  }
341
342
 
343
+ /**
344
+ * Generates a new flag document ID.
345
+ * @returns {string} The ID of the flag document that was generated.
346
+ */
347
+ exports.generateUserFlagID = userId => {
348
+ return `${DocumentTypes.USER_FLAG}${SEPARATOR}${userId}`
349
+ }
350
+
342
351
  exports.generateMetadataID = (type, entityId) => {
343
352
  return `${DocumentTypes.METADATA}${SEPARATOR}${type}${SEPARATOR}${entityId}`
344
353
  }