@budibase/server 1.0.6 → 1.0.8-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 (212) hide show
  1. package/builder/assets/{index.4fb3f887.css → index.9337c392.css} +1 -1
  2. package/builder/assets/{index.8b07ec4f.js → index.db2ce927.js} +160 -160
  3. package/builder/assets/{vendor.470042a4.js → vendor.a9288856.js} +1 -1
  4. package/builder/index.html +3 -3
  5. package/coverage/clover.xml +369 -330
  6. package/coverage/coverage-final.json +11 -10
  7. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/application.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/datasource.js.html +14 -14
  16. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/hosting.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/index.html +9 -24
  19. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/query/index.html +126 -0
  24. package/coverage/lcov-report/api/controllers/{query.js.html → query/index.js.html} +150 -24
  25. package/coverage/lcov-report/api/controllers/query/validation.js.html +200 -0
  26. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  38. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/table/internal.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/table/utils.js.html +5 -2
  41. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/view/index.html +15 -15
  45. package/coverage/lcov-report/api/controllers/view/index.js.html +52 -10
  46. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  47. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  48. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  49. package/coverage/lcov-report/api/index.html +1 -1
  50. package/coverage/lcov-report/api/index.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/index.html +9 -9
  64. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/query.js.html +11 -98
  70. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/static.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  81. package/coverage/lcov-report/automations/actions.js.html +1 -1
  82. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  83. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  84. package/coverage/lcov-report/automations/index.html +1 -1
  85. package/coverage/lcov-report/automations/index.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/index.html +1 -1
  95. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  98. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  99. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  100. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  101. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  102. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  103. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  106. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  107. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  108. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  109. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  110. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  111. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  112. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  113. package/coverage/lcov-report/automations/utils.js.html +1 -1
  114. package/coverage/lcov-report/constants/index.html +1 -1
  115. package/coverage/lcov-report/constants/index.js.html +1 -1
  116. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  117. package/coverage/lcov-report/constants/screens.js.html +1 -1
  118. package/coverage/lcov-report/db/client.js.html +1 -1
  119. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  120. package/coverage/lcov-report/db/index.html +1 -1
  121. package/coverage/lcov-report/db/index.js.html +1 -1
  122. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  123. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  124. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  125. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  126. package/coverage/lcov-report/db/newid.js.html +4 -4
  127. package/coverage/lcov-report/db/utils.js.html +58 -58
  128. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  129. package/coverage/lcov-report/events/index.html +1 -1
  130. package/coverage/lcov-report/events/index.js.html +1 -1
  131. package/coverage/lcov-report/events/utils.js.html +1 -1
  132. package/coverage/lcov-report/index.html +55 -40
  133. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  134. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  135. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  136. package/coverage/lcov-report/middleware/authorized.js.html +2 -2
  137. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  138. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  139. package/coverage/lcov-report/middleware/index.html +1 -1
  140. package/coverage/lcov-report/middleware/joi-validator.js.html +3 -3
  141. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  142. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  143. package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
  144. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  145. package/coverage/lcov-report/threads/automation.js.html +1 -1
  146. package/coverage/lcov-report/threads/index.html +1 -1
  147. package/coverage/lcov-report/threads/index.js.html +1 -1
  148. package/coverage/lcov-report/threads/query.js.html +1 -1
  149. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  150. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  151. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  152. package/coverage/lcov-report/utilities/csvParser.js.html +19 -10
  153. package/coverage/lcov-report/utilities/global.js.html +1 -1
  154. package/coverage/lcov-report/utilities/index.html +14 -14
  155. package/coverage/lcov-report/utilities/index.js.html +1 -1
  156. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  157. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  158. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  159. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  160. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  161. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  162. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  163. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  164. package/coverage/lcov-report/utilities/security.js.html +1 -1
  165. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  166. package/coverage/lcov-report/utilities/users.js.html +1 -1
  167. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  168. package/coverage/lcov.info +538 -480
  169. package/dist/api/controllers/query/import/index.js +79 -0
  170. package/dist/api/controllers/query/import/sources/base/index.js +63 -0
  171. package/dist/api/controllers/query/import/sources/base/openapi.js +42 -0
  172. package/dist/api/controllers/query/import/sources/curl.js +90 -0
  173. package/dist/api/controllers/query/import/sources/openapi2.js +139 -0
  174. package/dist/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
  175. package/dist/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
  176. package/dist/api/controllers/{query.js → query/index.js} +38 -4
  177. package/dist/api/controllers/query/validation.js +36 -0
  178. package/dist/api/controllers/view/index.js +15 -2
  179. package/dist/api/routes/query.js +2 -32
  180. package/dist/package.json +8 -4
  181. package/dist/tsconfig.tsbuildinfo +1 -1
  182. package/dist/utilities/csvParser.js +5 -2
  183. package/package.json +9 -5
  184. package/src/api/controllers/query/import/index.ts +85 -0
  185. package/src/api/controllers/query/import/sources/base/index.ts +86 -0
  186. package/src/api/controllers/query/import/sources/base/openapi.ts +24 -0
  187. package/src/api/controllers/query/import/sources/curl.ts +94 -0
  188. package/src/api/controllers/query/import/sources/openapi2.ts +159 -0
  189. package/src/api/controllers/query/import/sources/tests/curl/curl.spec.js +104 -0
  190. package/src/api/controllers/query/import/sources/tests/curl/data/delete.txt +1 -0
  191. package/src/api/controllers/query/import/sources/tests/curl/data/empty-body.txt +2 -0
  192. package/src/api/controllers/query/import/sources/tests/curl/data/get.txt +1 -0
  193. package/src/api/controllers/query/import/sources/tests/curl/data/headers.txt +3 -0
  194. package/src/api/controllers/query/import/sources/tests/curl/data/patch.txt +2 -0
  195. package/src/api/controllers/query/import/sources/tests/curl/data/path.txt +1 -0
  196. package/src/api/controllers/query/import/sources/tests/curl/data/post.txt +2 -0
  197. package/src/api/controllers/query/import/sources/tests/curl/data/put.txt +2 -0
  198. package/src/api/controllers/query/import/sources/tests/curl/data/query.txt +1 -0
  199. package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
  200. package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.yaml +160 -0
  201. package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
  202. package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.yaml +711 -0
  203. package/src/api/controllers/query/import/sources/tests/openapi2/openapi2.spec.js +239 -0
  204. package/src/api/controllers/query/import/tests/index.spec.js +115 -0
  205. package/src/api/controllers/{query.js → query/index.js} +46 -4
  206. package/src/api/controllers/query/validation.js +40 -0
  207. package/src/api/controllers/table/utils.js +1 -0
  208. package/src/api/controllers/view/index.js +16 -2
  209. package/src/api/routes/query.js +5 -34
  210. package/src/definitions/common.ts +22 -0
  211. package/src/integrations/oracle.ts +1 -1
  212. package/src/utilities/csvParser.js +5 -2
@@ -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
@@ -0,0 +1,40 @@
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
+ })
23
+ }
24
+
25
+ exports.generateQueryValidation = () => {
26
+ // prettier-ignore
27
+ return joiValidator.body(exports.queryValidation())
28
+ }
29
+
30
+ exports.generateQueryPreviewValidation = () => {
31
+ // prettier-ignore
32
+ return joiValidator.body(Joi.object({
33
+ fields: Joi.object().required(),
34
+ queryVerb: Joi.string().allow().required(),
35
+ extra: Joi.object().optional(),
36
+ datasourceId: Joi.string().required(),
37
+ transformer: Joi.string().optional(),
38
+ parameters: Joi.object({}).required().unknown(true)
39
+ }))
40
+ }
@@ -75,6 +75,7 @@ exports.handleDataImport = async (appId, user, table, dataImport) => {
75
75
  if (!dataImport || !dataImport.csvString) {
76
76
  return table
77
77
  }
78
+
78
79
  const db = new CouchDB(appId)
79
80
  // Populate the table with rows imported from CSV in a bulk update
80
81
  const data = await csvParser.transform({
@@ -5,6 +5,7 @@ const exporters = require("./exporters")
5
5
  const { saveView, getView, getViews, deleteView } = require("./utils")
6
6
  const { fetchView } = require("../row")
7
7
  const { getTable } = require("../table/utils")
8
+ const { FieldTypes } = require("../../../constants")
8
9
 
9
10
  exports.fetch = async ctx => {
10
11
  const db = new CouchDB(ctx.appId)
@@ -77,6 +78,7 @@ exports.exportView = async ctx => {
77
78
  }
78
79
 
79
80
  await fetchView(ctx)
81
+ let rows = ctx.body
80
82
 
81
83
  let schema = view && view.meta && view.meta.schema
82
84
  if (!schema) {
@@ -85,11 +87,23 @@ exports.exportView = async ctx => {
85
87
  schema = table.schema
86
88
  }
87
89
 
90
+ // remove any relationships
91
+ const relationships = Object.entries(schema)
92
+ .filter(entry => entry[1].type === FieldTypes.LINK)
93
+ .map(entry => entry[0])
94
+ // iterate relationship columns and remove from and row and schema
95
+ relationships.forEach(column => {
96
+ rows.forEach(row => {
97
+ delete row[column]
98
+ })
99
+ delete schema[column]
100
+ })
101
+
88
102
  // make sure no "undefined" entries appear in the CSV
89
103
  if (format === exporters.ExportFormats.CSV) {
90
104
  const schemaKeys = Object.keys(schema)
91
105
  for (let key of schemaKeys) {
92
- for (let row of ctx.body) {
106
+ for (let row of rows) {
93
107
  if (row[key] == null) {
94
108
  row[key] = ""
95
109
  }
@@ -103,5 +117,5 @@ exports.exportView = async ctx => {
103
117
  const filename = `${viewName}.${format}`
104
118
  // send down the file
105
119
  ctx.attachment(filename)
106
- ctx.body = apiFileReturn(exporter(headers, ctx.body))
120
+ ctx.body = apiFileReturn(exporter(headers, rows))
107
121
  }
@@ -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"),
@@ -107,3 +107,25 @@ export interface Datasource extends Base {
107
107
  [key: string]: Table
108
108
  }
109
109
  }
110
+
111
+ export interface QueryParameter {
112
+ name: string
113
+ default: string
114
+ }
115
+
116
+ export interface Query {
117
+ _id?: string
118
+ datasourceId: string
119
+ name: string
120
+ parameters: QueryParameter[]
121
+ fields: {
122
+ headers: object
123
+ queryString: string | null
124
+ path: string
125
+ requestBody: string | undefined
126
+ }
127
+ transformer: string | null
128
+ schema: any
129
+ readable: boolean
130
+ queryVerb: string
131
+ }
@@ -450,7 +450,7 @@ module OracleModule {
450
450
  })
451
451
  return lastRow.rows
452
452
  } else {
453
- return [{ [ operation.toLowerCase() ]: true }]
453
+ return [{ [operation.toLowerCase()]: true }]
454
454
  }
455
455
  }
456
456
  }
@@ -102,8 +102,11 @@ async function transform({ schema, csvString, existingTable }) {
102
102
  schema = updateSchema({ schema, existingTable })
103
103
  }
104
104
 
105
- for (let key of Object.keys(schema)) {
106
- colParser[key] = PARSERS[schema[key].type] || schema[key].type
105
+ for (let [key, field] of Object.entries(schema)) {
106
+ // don't import data to auto columns
107
+ if (!field.autocolumn) {
108
+ colParser[key] = PARSERS[field.type] || field.type
109
+ }
107
110
  }
108
111
 
109
112
  try {