@budibase/server 1.0.90 → 1.0.91-alpha.10

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 (211) hide show
  1. package/builder/assets/{index.7c8961b4.css → index.9ae0eacb.css} +1 -1
  2. package/builder/assets/{index.5cea89f7.js → index.aa487b9b.js} +212 -212
  3. package/builder/assets/{vendor.a7c6ad0a.js → vendor.8e34a169.js} +1 -1
  4. package/builder/index.html +3 -3
  5. package/coverage/clover.xml +192 -191
  6. package/coverage/coverage-final.json +10 -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 +1 -1
  16. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/index.html +1 -1
  18. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/migrations.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 +1 -1
  24. package/coverage/lcov-report/api/controllers/query/index.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/query/validation.js.html +2 -2
  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 +10 -10
  30. package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/row/internal.js.html +19 -7
  32. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/row/utils.js.html +6 -6
  35. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/table/bulkFormula.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 +1 -1
  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 +1 -1
  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 +3 -3
  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/index.html +1 -1
  65. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/migrations.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 +1 -1
  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 +1 -1
  81. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  82. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  83. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  84. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  85. package/coverage/lcov-report/automations/actions.js.html +1 -1
  86. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  87. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  88. package/coverage/lcov-report/automations/index.html +1 -1
  89. package/coverage/lcov-report/automations/index.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  98. package/coverage/lcov-report/automations/steps/index.html +1 -1
  99. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  100. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  101. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  102. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  103. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  104. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  105. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  106. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  107. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  108. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  109. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  110. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  111. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  112. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  113. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  114. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  115. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  116. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  117. package/coverage/lcov-report/automations/utils.js.html +1 -1
  118. package/coverage/lcov-report/constants/index.html +1 -1
  119. package/coverage/lcov-report/constants/index.js.html +1 -1
  120. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  121. package/coverage/lcov-report/constants/screens.js.html +1 -1
  122. package/coverage/lcov-report/db/client.js.html +1 -1
  123. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  124. package/coverage/lcov-report/db/index.html +1 -1
  125. package/coverage/lcov-report/db/index.js.html +1 -1
  126. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  127. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  128. package/coverage/lcov-report/db/linkedRows/index.js.html +11 -11
  129. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +7 -7
  130. package/coverage/lcov-report/db/newid.js.html +2 -2
  131. package/coverage/lcov-report/db/utils.js.html +2 -2
  132. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  133. package/coverage/lcov-report/events/index.html +1 -1
  134. package/coverage/lcov-report/events/index.js.html +1 -1
  135. package/coverage/lcov-report/events/utils.js.html +1 -1
  136. package/coverage/lcov-report/index.html +10 -10
  137. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  138. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  139. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  140. package/coverage/lcov-report/middleware/authorized.js.html +1 -1
  141. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  142. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  143. package/coverage/lcov-report/middleware/index.html +1 -1
  144. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  145. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  146. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  147. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  148. package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
  149. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  150. package/coverage/lcov-report/threads/automation.js.html +1 -1
  151. package/coverage/lcov-report/threads/index.html +1 -1
  152. package/coverage/lcov-report/threads/index.js.html +1 -1
  153. package/coverage/lcov-report/threads/query.js.html +1 -1
  154. package/coverage/lcov-report/threads/utils.js.html +1 -1
  155. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  156. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  157. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  158. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  159. package/coverage/lcov-report/utilities/global.js.html +1 -1
  160. package/coverage/lcov-report/utilities/index.html +1 -1
  161. package/coverage/lcov-report/utilities/index.js.html +1 -1
  162. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  163. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  164. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  165. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  166. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  167. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +12 -12
  168. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +8 -8
  169. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  170. package/coverage/lcov-report/utilities/security.js.html +1 -1
  171. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  172. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  173. package/coverage/lcov-report/utilities/usageQuota/index.js.html +1 -1
  174. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  175. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  176. package/coverage/lcov-report/utilities/users.js.html +1 -1
  177. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  178. package/coverage/lcov.info +281 -280
  179. package/dist/api/controllers/query/import/index.js +2 -1
  180. package/dist/api/controllers/query/import/sources/base/index.js +12 -1
  181. package/dist/api/controllers/query/import/sources/curl.js +2 -2
  182. package/dist/api/controllers/query/import/sources/openapi3.js +174 -0
  183. package/dist/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.json +253 -0
  184. package/dist/api/controllers/query/import/sources/tests/openapi3/data/petstore/petstore.json +1225 -0
  185. package/dist/api/controllers/row/internal.js +2 -1
  186. package/dist/api/routes/analytics.js +2 -2
  187. package/dist/definitions/datasource.js +1 -0
  188. package/dist/integrations/base/sql.js +16 -9
  189. package/dist/integrations/firebase.js +192 -0
  190. package/dist/integrations/index.js +3 -0
  191. package/dist/package.json +5 -4
  192. package/dist/tsconfig.tsbuildinfo +1 -1
  193. package/package.json +6 -5
  194. package/src/api/controllers/query/import/index.ts +2 -1
  195. package/src/api/controllers/query/import/sources/base/index.ts +12 -2
  196. package/src/api/controllers/query/import/sources/curl.ts +2 -2
  197. package/src/api/controllers/query/import/sources/openapi3.ts +205 -0
  198. package/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.json +253 -0
  199. package/src/api/controllers/query/import/sources/tests/openapi3/data/crud/crud.yaml +153 -0
  200. package/src/api/controllers/query/import/sources/tests/openapi3/data/petstore/petstore.json +1225 -0
  201. package/src/api/controllers/query/import/sources/tests/openapi3/data/petstore/petstore.yaml +804 -0
  202. package/src/api/controllers/query/import/sources/tests/openapi3/openapi3.spec.js +240 -0
  203. package/src/api/controllers/query/import/tests/index.spec.js +43 -0
  204. package/src/api/controllers/row/internal.js +5 -1
  205. package/src/api/routes/analytics.js +2 -2
  206. package/src/api/routes/tests/misc.spec.js +2 -2
  207. package/src/definitions/datasource.ts +1 -0
  208. package/src/integrations/base/sql.ts +14 -9
  209. package/src/integrations/firebase.ts +205 -0
  210. package/src/integrations/index.ts +3 -0
  211. package/src/integrations/tests/sql.spec.js +51 -0
@@ -0,0 +1,240 @@
1
+ const fs = require("fs")
2
+ const path = require("path")
3
+
4
+ const { OpenAPI3 } = require("../../openapi3")
5
+
6
+ const getData = (file, extension) => {
7
+ return fs.readFileSync(
8
+ path.join(__dirname, `./data/${file}/${file}.${extension}`),
9
+ "utf8"
10
+ )
11
+ }
12
+
13
+ describe("OpenAPI3 Import", () => {
14
+ let openapi3
15
+
16
+ beforeEach(() => {
17
+ openapi3 = new OpenAPI3()
18
+ })
19
+
20
+ it("validates unsupported data", async () => {
21
+ let data
22
+ let supported
23
+
24
+ // non json / yaml
25
+ data = "curl http://example.com"
26
+ supported = await openapi3.isSupported(data)
27
+ expect(supported).toBe(false)
28
+
29
+ // Empty
30
+ data = ""
31
+ supported = await openapi3.isSupported(data)
32
+ expect(supported).toBe(false)
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 openapi3.isSupported(getData(file, extension))
43
+ const info = await openapi3.getInfo()
44
+ expect(info.name).toBe("Swagger Petstore - OpenAPI 3.0")
45
+ }
46
+
47
+ it("returns import info", async () => {
48
+ await runTests("petstore", testImportInfo)
49
+ })
50
+
51
+ describe("Returns queries", () => {
52
+ const indexQueries = queries => {
53
+ return queries.reduce((acc, query) => {
54
+ acc[query.name] = query
55
+ return acc
56
+ }, {})
57
+ }
58
+
59
+ const getQueries = async (file, extension) => {
60
+ await openapi3.isSupported(getData(file, extension))
61
+ const queries = await openapi3.getQueries()
62
+ expect(queries.length).toBe(6)
63
+ return indexQueries(queries)
64
+ }
65
+
66
+ const testVerb = async (file, extension, assertions) => {
67
+ const queries = await getQueries(file, extension)
68
+ for (let [operationId, method] of Object.entries(assertions)) {
69
+ expect(queries[operationId].queryVerb).toBe(method)
70
+ }
71
+ }
72
+
73
+ it("populates verb", async () => {
74
+ const assertions = {
75
+ createEntity: "create",
76
+ getEntities: "read",
77
+ getEntity: "read",
78
+ updateEntity: "update",
79
+ patchEntity: "patch",
80
+ deleteEntity: "delete",
81
+ }
82
+ await runTests("crud", testVerb, assertions)
83
+ })
84
+
85
+ const testPath = async (file, extension, assertions) => {
86
+ const queries = await getQueries(file, extension)
87
+ for (let [operationId, urlPath] of Object.entries(assertions)) {
88
+ expect(queries[operationId].fields.path).toBe(urlPath)
89
+ }
90
+ }
91
+
92
+ it("populates path", async () => {
93
+ const assertions = {
94
+ createEntity: "http://example.com/entities",
95
+ getEntities: "http://example.com/entities",
96
+ getEntity: "http://example.com/entities/{{entityId}}",
97
+ updateEntity: "http://example.com/entities/{{entityId}}",
98
+ patchEntity: "http://example.com/entities/{{entityId}}",
99
+ deleteEntity: "http://example.com/entities/{{entityId}}",
100
+ }
101
+ await runTests("crud", testPath, assertions)
102
+ })
103
+
104
+ const testHeaders = async (file, extension, assertions) => {
105
+ const queries = await getQueries(file, extension)
106
+ for (let [operationId, headers] of Object.entries(assertions)) {
107
+ expect(queries[operationId].fields.headers).toStrictEqual(headers)
108
+ }
109
+ }
110
+
111
+ const contentTypeHeader = {
112
+ "Content-Type": "application/json",
113
+ }
114
+
115
+ it("populates headers", async () => {
116
+ const assertions = {
117
+ createEntity: {
118
+ ...contentTypeHeader,
119
+ },
120
+ getEntities: {},
121
+ getEntity: {},
122
+ updateEntity: {
123
+ ...contentTypeHeader,
124
+ },
125
+ patchEntity: {
126
+ ...contentTypeHeader,
127
+ },
128
+ deleteEntity: {
129
+ "x-api-key": "{{x-api-key}}",
130
+ },
131
+ }
132
+
133
+ await runTests("crud", testHeaders, assertions)
134
+ })
135
+
136
+ const testQuery = async (file, extension, assertions) => {
137
+ const queries = await getQueries(file, extension)
138
+ for (let [operationId, queryString] of Object.entries(assertions)) {
139
+ expect(queries[operationId].fields.queryString).toStrictEqual(
140
+ queryString
141
+ )
142
+ }
143
+ }
144
+
145
+ it("populates query", async () => {
146
+ const assertions = {
147
+ createEntity: "",
148
+ getEntities: "page={{page}}&size={{size}}",
149
+ getEntity: "",
150
+ updateEntity: "",
151
+ patchEntity: "",
152
+ deleteEntity: "",
153
+ }
154
+ await runTests("crud", testQuery, assertions)
155
+ })
156
+
157
+ const testParameters = async (file, extension, assertions) => {
158
+ const queries = await getQueries(file, extension)
159
+ for (let [operationId, parameters] of Object.entries(assertions)) {
160
+ expect(queries[operationId].parameters).toStrictEqual(parameters)
161
+ }
162
+ }
163
+
164
+ it("populates parameters", async () => {
165
+ const assertions = {
166
+ createEntity: [],
167
+ getEntities: [
168
+ {
169
+ name: "page",
170
+ default: "",
171
+ },
172
+ {
173
+ name: "size",
174
+ default: "",
175
+ },
176
+ ],
177
+ getEntity: [
178
+ {
179
+ name: "entityId",
180
+ default: "",
181
+ },
182
+ ],
183
+ updateEntity: [
184
+ {
185
+ name: "entityId",
186
+ default: "",
187
+ },
188
+ ],
189
+ patchEntity: [
190
+ {
191
+ name: "entityId",
192
+ default: "",
193
+ },
194
+ ],
195
+ deleteEntity: [
196
+ {
197
+ name: "entityId",
198
+ default: "",
199
+ },
200
+ {
201
+ name: "x-api-key",
202
+ default: "",
203
+ },
204
+ ],
205
+ }
206
+ await runTests("crud", testParameters, assertions)
207
+ })
208
+
209
+ const testBody = async (file, extension, assertions) => {
210
+ const queries = await getQueries(file, extension)
211
+ for (let [operationId, body] of Object.entries(assertions)) {
212
+ expect(queries[operationId].fields.requestBody).toStrictEqual(
213
+ JSON.stringify(body, null, 2)
214
+ )
215
+ }
216
+ }
217
+ it("populates body", async () => {
218
+ const assertions = {
219
+ createEntity: {
220
+ name: "name",
221
+ type: "type",
222
+ },
223
+ getEntities: undefined,
224
+ getEntity: undefined,
225
+ updateEntity: {
226
+ id: 1,
227
+ name: "name",
228
+ type: "type",
229
+ },
230
+ patchEntity: {
231
+ id: 1,
232
+ name: "name",
233
+ type: "type",
234
+ },
235
+ deleteEntity: undefined,
236
+ }
237
+ await runTests("crud", testBody, assertions)
238
+ })
239
+ })
240
+ })
@@ -23,14 +23,27 @@ const oapi2CrudYaml = getData("openapi2/data/crud/crud.json")
23
23
  const oapi2PetstoreJson = getData("openapi2/data/petstore/petstore.json")
24
24
  const oapi2PetstoreYaml = getData("openapi2/data/petstore/petstore.json")
25
25
 
26
+ // openapi3
27
+ const oapi3CrudJson = getData("openapi3/data/crud/crud.json")
28
+ const oapi3CrudYaml = getData("openapi3/data/crud/crud.json")
29
+ const oapi3PetstoreJson = getData("openapi3/data/petstore/petstore.json")
30
+ const oapi3PetstoreYaml = getData("openapi3/data/petstore/petstore.json")
31
+
26
32
  // curl
27
33
  const curl = getData("curl/data/post.txt")
28
34
 
29
35
  const datasets = {
36
+ // openapi2 (swagger)
30
37
  oapi2CrudJson,
31
38
  oapi2CrudYaml,
32
39
  oapi2PetstoreJson,
33
40
  oapi2PetstoreYaml,
41
+ // openapi3
42
+ oapi3CrudJson,
43
+ oapi3CrudYaml,
44
+ oapi3PetstoreJson,
45
+ oapi3PetstoreYaml,
46
+ // curl
34
47
  curl
35
48
  }
36
49
 
@@ -56,6 +69,7 @@ describe("Rest Importer", () => {
56
69
 
57
70
  it("gets info", async () => {
58
71
  const assertions = {
72
+ // openapi2 (swagger)
59
73
  "oapi2CrudJson" : {
60
74
  name: "CRUD",
61
75
  },
@@ -68,6 +82,20 @@ describe("Rest Importer", () => {
68
82
  "oapi2PetstoreYaml" :{
69
83
  name: "Swagger Petstore",
70
84
  },
85
+ // openapi3
86
+ "oapi3CrudJson" : {
87
+ name: "CRUD",
88
+ },
89
+ "oapi3CrudYaml" : {
90
+ name: "CRUD",
91
+ },
92
+ "oapi3PetstoreJson" : {
93
+ name: "Swagger Petstore - OpenAPI 3.0",
94
+ },
95
+ "oapi3PetstoreYaml" :{
96
+ name: "Swagger Petstore - OpenAPI 3.0",
97
+ },
98
+ // curl
71
99
  "curl": {
72
100
  name: "example.com",
73
101
  }
@@ -89,6 +117,7 @@ describe("Rest Importer", () => {
89
117
  // simple sanity assertions that the whole dataset
90
118
  // makes it through the importer
91
119
  const assertions = {
120
+ // openapi2 (swagger)
92
121
  "oapi2CrudJson" : {
93
122
  count: 6,
94
123
  },
@@ -101,6 +130,20 @@ describe("Rest Importer", () => {
101
130
  "oapi2PetstoreYaml" :{
102
131
  count: 20,
103
132
  },
133
+ // openapi3
134
+ "oapi3CrudJson" : {
135
+ count: 6,
136
+ },
137
+ "oapi3CrudYaml" :{
138
+ count: 6,
139
+ },
140
+ "oapi3PetstoreJson" : {
141
+ count: 19,
142
+ },
143
+ "oapi3PetstoreYaml" :{
144
+ count: 19,
145
+ },
146
+ // curl
104
147
  "curl": {
105
148
  count: 1
106
149
  }
@@ -85,7 +85,11 @@ exports.patch = async ctx => {
85
85
  const isUserTable = tableId === InternalTables.USER_METADATA
86
86
  let oldRow
87
87
  try {
88
- oldRow = await db.get(inputs._id)
88
+ let dbTable = await db.get(tableId)
89
+ oldRow = await outputProcessing(
90
+ dbTable,
91
+ await findRow(ctx, tableId, inputs._id)
92
+ )
89
93
  } catch (err) {
90
94
  if (isUserTable) {
91
95
  // don't include the rev, it'll be the global rev
@@ -4,7 +4,7 @@ const controller = require("../controllers/analytics")
4
4
  const router = Router()
5
5
 
6
6
  router
7
- .get("/api/analytics", controller.isEnabled)
8
- .post("/api/analytics/ping", controller.endUserPing)
7
+ .get("/api/bbtel", controller.isEnabled)
8
+ .post("/api/bbtel/ping", controller.endUserPing)
9
9
 
10
10
  module.exports = router
@@ -11,10 +11,10 @@ describe("run misc tests", () => {
11
11
  await config.init()
12
12
  })
13
13
 
14
- describe("/analytics", () => {
14
+ describe("/bbtel", () => {
15
15
  it("check if analytics enabled", async () => {
16
16
  const res = await request
17
- .get(`/api/analytics`)
17
+ .get(`/api/bbtel`)
18
18
  .set(config.defaultHeaders())
19
19
  .expect("Content-Type", /json/)
20
20
  .expect(200)
@@ -48,6 +48,7 @@ export enum SourceNames {
48
48
  REST = "REST",
49
49
  ORACLE = "ORACLE",
50
50
  GOOGLE_SHEETS = "GOOGLE_SHEETS",
51
+ FIREBASE = "FIREBASE",
51
52
  }
52
53
 
53
54
  export enum IncludeRelationships {
@@ -27,11 +27,8 @@ function parse(input: any) {
27
27
  if (typeof input !== "string") {
28
28
  return input
29
29
  }
30
- if (input === MAX_ISO_DATE) {
31
- return new Date(8640000000000000)
32
- }
33
- if (input === MIN_ISO_DATE) {
34
- return new Date(-8640000000000000)
30
+ if (input === MAX_ISO_DATE || input === MIN_ISO_DATE) {
31
+ return null
35
32
  }
36
33
  if (isIsoDateString(input)) {
37
34
  return new Date(input)
@@ -130,11 +127,19 @@ class InternalBuilder {
130
127
  }
131
128
  if (filters.range) {
132
129
  iterate(filters.range, (key, value) => {
133
- if (!value.high || !value.low) {
134
- return
130
+ if (value.low && value.high) {
131
+ // Use a between operator if we have 2 valid range values
132
+ const fnc = allOr ? "orWhereBetween" : "whereBetween"
133
+ query = query[fnc](key, [value.low, value.high])
134
+ } else if (value.low) {
135
+ // Use just a single greater than operator if we only have a low
136
+ const fnc = allOr ? "orWhere" : "where"
137
+ query = query[fnc](key, ">", value.low)
138
+ } else if (value.high) {
139
+ // Use just a single less than operator if we only have a high
140
+ const fnc = allOr ? "orWhere" : "where"
141
+ query = query[fnc](key, "<", value.high)
135
142
  }
136
- const fnc = allOr ? "orWhereBetween" : "whereBetween"
137
- query = query[fnc](key, [value.low, value.high])
138
143
  })
139
144
  }
140
145
  if (filters.equal) {
@@ -0,0 +1,205 @@
1
+ import {
2
+ DatasourceFieldTypes,
3
+ Integration,
4
+ QueryTypes,
5
+ } from "../definitions/datasource"
6
+ import { IntegrationBase } from "./base/IntegrationBase"
7
+ import { Firestore, WhereFilterOp } from "@google-cloud/firestore"
8
+
9
+ module Firebase {
10
+ interface FirebaseConfig {
11
+ email: string
12
+ privateKey: string
13
+ projectId: string
14
+ serviceAccount?: string
15
+ }
16
+
17
+ const SCHEMA: Integration = {
18
+ docs: "https://firebase.google.com/docs/firestore/quickstart",
19
+ friendlyName: "Firestore",
20
+ description:
21
+ "Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud.",
22
+ datasource: {
23
+ email: {
24
+ type: DatasourceFieldTypes.STRING,
25
+ required: true,
26
+ },
27
+ privateKey: {
28
+ type: DatasourceFieldTypes.STRING,
29
+ required: true,
30
+ },
31
+ projectId: {
32
+ type: DatasourceFieldTypes.STRING,
33
+ required: true,
34
+ },
35
+ serviceAccount: {
36
+ type: DatasourceFieldTypes.JSON,
37
+ required: false,
38
+ },
39
+ },
40
+ query: {
41
+ create: {
42
+ type: QueryTypes.JSON,
43
+ },
44
+ read: {
45
+ type: QueryTypes.JSON,
46
+ },
47
+ update: {
48
+ type: QueryTypes.JSON,
49
+ },
50
+ delete: {
51
+ type: QueryTypes.JSON,
52
+ },
53
+ },
54
+ extra: {
55
+ collection: {
56
+ displayName: "Collection",
57
+ type: DatasourceFieldTypes.STRING,
58
+ required: true,
59
+ },
60
+ filterField: {
61
+ displayName: "Filter field",
62
+ type: DatasourceFieldTypes.STRING,
63
+ required: false,
64
+ },
65
+ filter: {
66
+ displayName: "Filter comparison",
67
+ type: DatasourceFieldTypes.LIST,
68
+ required: false,
69
+ data: {
70
+ read: [
71
+ "==",
72
+ "<",
73
+ "<=",
74
+ "==",
75
+ "!=",
76
+ ">=",
77
+ ">",
78
+ "array-contains",
79
+ "in",
80
+ "not-in",
81
+ "array-contains-any",
82
+ ],
83
+ },
84
+ },
85
+ filterValue: {
86
+ displayName: "Filter value",
87
+ type: DatasourceFieldTypes.STRING,
88
+ required: false,
89
+ },
90
+ },
91
+ }
92
+
93
+ class FirebaseIntegration implements IntegrationBase {
94
+ private config: FirebaseConfig
95
+ private db: Firestore
96
+
97
+ constructor(config: FirebaseConfig) {
98
+ this.config = config
99
+ if (config.serviceAccount) {
100
+ const serviceAccount = JSON.parse(config.serviceAccount)
101
+ this.db = new Firestore({
102
+ projectId: serviceAccount.project_id,
103
+ credentials: {
104
+ client_email: serviceAccount.client_email,
105
+ private_key: serviceAccount.private_key,
106
+ },
107
+ })
108
+ } else {
109
+ this.db = new Firestore({
110
+ projectId: config.projectId,
111
+ credentials: {
112
+ client_email: config.email,
113
+ private_key: config.privateKey,
114
+ },
115
+ })
116
+ }
117
+ }
118
+
119
+ async create(query: { json: object; extra: { [key: string]: string } }) {
120
+ try {
121
+ const documentReference = this.db
122
+ .collection(query.extra.collection)
123
+ .doc()
124
+ await documentReference.set({ ...query.json, id: documentReference.id })
125
+ const snapshot = await documentReference.get()
126
+ return snapshot.data()
127
+ } catch (err) {
128
+ console.error("Error writing to Firestore", err)
129
+ throw err
130
+ }
131
+ }
132
+
133
+ async read(query: { json: object; extra: { [key: string]: string } }) {
134
+ try {
135
+ let snapshot
136
+ const collectionRef = this.db.collection(query.extra.collection)
137
+ if (
138
+ query.extra.filterField &&
139
+ query.extra.filter &&
140
+ query.extra.filterValue
141
+ ) {
142
+ snapshot = await collectionRef
143
+ .where(
144
+ query.extra.filterField,
145
+ query.extra.filter as WhereFilterOp,
146
+ query.extra.filterValue
147
+ )
148
+ .get()
149
+ } else {
150
+ snapshot = await collectionRef.get()
151
+ }
152
+ const result: any[] = []
153
+ snapshot.forEach(doc => result.push(doc.data()))
154
+
155
+ return result
156
+ } catch (err) {
157
+ console.error("Error querying Firestore", err)
158
+ throw err
159
+ }
160
+ }
161
+
162
+ async update(query: {
163
+ json: Record<string, any>
164
+ extra: { [key: string]: string }
165
+ }) {
166
+ try {
167
+ await this.db
168
+ .collection(query.extra.collection)
169
+ .doc(query.json.id)
170
+ .update(query.json)
171
+
172
+ return (
173
+ await this.db
174
+ .collection(query.extra.collection)
175
+ .doc(query.json.id)
176
+ .get()
177
+ ).data()
178
+ } catch (err) {
179
+ console.error("Error writing to firebase", err)
180
+ throw err
181
+ }
182
+ }
183
+
184
+ async delete(query: {
185
+ json: { id: string }
186
+ extra: { [key: string]: string }
187
+ }) {
188
+ try {
189
+ await this.db
190
+ .collection(query.extra.collection)
191
+ .doc(query.json.id)
192
+ .delete()
193
+ return true
194
+ } catch (err) {
195
+ console.error("Error writing to mongodb", err)
196
+ throw err
197
+ }
198
+ }
199
+ }
200
+
201
+ module.exports = {
202
+ schema: SCHEMA,
203
+ integration: FirebaseIntegration,
204
+ }
205
+ }
@@ -10,6 +10,7 @@ const mysql = require("./mysql")
10
10
  const arangodb = require("./arangodb")
11
11
  const rest = require("./rest")
12
12
  const googlesheets = require("./googlesheets")
13
+ const firebase = require("./firebase")
13
14
  const { SourceNames } = require("../definitions/datasource")
14
15
  const environment = require("../environment")
15
16
 
@@ -25,6 +26,7 @@ const DEFINITIONS = {
25
26
  [SourceNames.MYSQL]: mysql.schema,
26
27
  [SourceNames.ARANGODB]: arangodb.schema,
27
28
  [SourceNames.REST]: rest.schema,
29
+ [SourceNames.FIREBASE]: firebase.schema,
28
30
  }
29
31
 
30
32
  const INTEGRATIONS = {
@@ -39,6 +41,7 @@ const INTEGRATIONS = {
39
41
  [SourceNames.MYSQL]: mysql.integration,
40
42
  [SourceNames.ARANGODB]: arangodb.integration,
41
43
  [SourceNames.REST]: rest.integration,
44
+ [SourceNames.FIREBASE]: firebase.integration,
42
45
  }
43
46
 
44
47
  // optionally add oracle integration if the oracle binary can be installed
@@ -187,4 +187,55 @@ describe("SQL query builder", () => {
187
187
  sql: `select * from (select * from \`${TABLE_NAME}\` limit ?) as \`${TABLE_NAME}\``
188
188
  })
189
189
  })
190
+
191
+ it("should use greater than when only low range specified", () => {
192
+ const date = new Date()
193
+ const query = sql._query(generateReadJson({
194
+ filters: {
195
+ range: {
196
+ property: {
197
+ low: date,
198
+ }
199
+ }
200
+ }
201
+ }))
202
+ expect(query).toEqual({
203
+ bindings: [date, limit],
204
+ sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."property" > $1 limit $2) as "${TABLE_NAME}"`
205
+ })
206
+ })
207
+
208
+ it("should use less than when only high range specified", () => {
209
+ const date = new Date()
210
+ const query = sql._query(generateReadJson({
211
+ filters: {
212
+ range: {
213
+ property: {
214
+ high: date,
215
+ }
216
+ }
217
+ }
218
+ }))
219
+ expect(query).toEqual({
220
+ bindings: [date, limit],
221
+ sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."property" < $1 limit $2) as "${TABLE_NAME}"`
222
+ })
223
+ })
224
+
225
+ it("should use greater than when only low range specified", () => {
226
+ const date = new Date()
227
+ const query = sql._query(generateReadJson({
228
+ filters: {
229
+ range: {
230
+ property: {
231
+ low: date,
232
+ }
233
+ }
234
+ }
235
+ }))
236
+ expect(query).toEqual({
237
+ bindings: [date, limit],
238
+ sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."property" > $1 limit $2) as "${TABLE_NAME}"`
239
+ })
240
+ })
190
241
  })