@budibase/server 1.0.35 → 1.0.39
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.
- package/__mocks__/node-fetch.ts +21 -0
- package/builder/assets/bb-spaceship.8f6e81e1.svg +227 -0
- package/builder/assets/index.3079d0f9.js +1348 -0
- package/builder/assets/{index.4fb3f887.css → index.39e01193.css} +1 -1
- package/builder/assets/{vendor.470042a4.js → vendor.f9faf6ab.js} +88 -88
- package/builder/index.html +3 -3
- package/coverage/clover.xml +1589 -1344
- package/coverage/coverage-final.json +75 -74
- package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
- package/coverage/lcov-report/api/controllers/apikeys.js.html +3 -3
- package/coverage/lcov-report/api/controllers/application.js.html +73 -64
- package/coverage/lcov-report/api/controllers/auth.js.html +2 -2
- package/coverage/lcov-report/api/controllers/automation.js.html +22 -10
- package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
- package/coverage/lcov-report/api/controllers/cloud.js.html +13 -4
- package/coverage/lcov-report/api/controllers/component.js.html +4 -4
- package/coverage/lcov-report/api/controllers/datasource.js.html +170 -68
- package/coverage/lcov-report/api/controllers/dev.js.html +3 -3
- package/coverage/lcov-report/api/controllers/hosting.js.html +3 -3
- package/coverage/lcov-report/api/controllers/index.html +39 -54
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
- package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
- package/coverage/lcov-report/api/controllers/permission.js.html +3 -3
- package/coverage/lcov-report/api/controllers/query/index.html +126 -0
- package/coverage/lcov-report/api/controllers/{query.js.html → query/index.js.html} +225 -120
- package/coverage/lcov-report/api/controllers/query/validation.js.html +206 -0
- package/coverage/lcov-report/api/controllers/role.js.html +2 -2
- package/coverage/lcov-report/api/controllers/routing.js.html +2 -2
- package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/index.html +22 -22
- package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/internal.js.html +38 -11
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +8 -5
- package/coverage/lcov-report/api/controllers/row/utils.js.html +29 -20
- package/coverage/lcov-report/api/controllers/screen.js.html +2 -2
- package/coverage/lcov-report/api/controllers/script.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/internal.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +120 -12
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
- package/coverage/lcov-report/api/controllers/webhook.js.html +19 -7
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +6 -6
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +2 -2
- package/coverage/lcov-report/api/routes/application.js.html +2 -2
- package/coverage/lcov-report/api/routes/auth.js.html +1 -1
- package/coverage/lcov-report/api/routes/automation.js.html +2 -2
- package/coverage/lcov-report/api/routes/backup.js.html +2 -2
- package/coverage/lcov-report/api/routes/cloud.js.html +2 -2
- package/coverage/lcov-report/api/routes/component.js.html +2 -2
- package/coverage/lcov-report/api/routes/datasource.js.html +2 -2
- package/coverage/lcov-report/api/routes/deploy.js.html +2 -2
- package/coverage/lcov-report/api/routes/dev.js.html +2 -2
- package/coverage/lcov-report/api/routes/hosting.js.html +2 -2
- package/coverage/lcov-report/api/routes/index.html +9 -9
- package/coverage/lcov-report/api/routes/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/integration.js.html +2 -2
- package/coverage/lcov-report/api/routes/layout.js.html +2 -2
- package/coverage/lcov-report/api/routes/metadata.js.html +2 -2
- package/coverage/lcov-report/api/routes/permission.js.html +12 -3
- package/coverage/lcov-report/api/routes/query.js.html +20 -86
- package/coverage/lcov-report/api/routes/role.js.html +2 -2
- package/coverage/lcov-report/api/routes/routing.js.html +2 -2
- package/coverage/lcov-report/api/routes/row.js.html +2 -2
- package/coverage/lcov-report/api/routes/screen.js.html +2 -2
- package/coverage/lcov-report/api/routes/script.js.html +2 -2
- package/coverage/lcov-report/api/routes/static.js.html +2 -2
- package/coverage/lcov-report/api/routes/table.js.html +2 -2
- package/coverage/lcov-report/api/routes/templates.js.html +2 -2
- package/coverage/lcov-report/api/routes/user.js.html +33 -3
- package/coverage/lcov-report/api/routes/view.js.html +2 -2
- package/coverage/lcov-report/api/routes/webhook.js.html +2 -2
- package/coverage/lcov-report/automations/actions.js.html +1 -1
- package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
- package/coverage/lcov-report/automations/bullboard.js.html +2 -2
- package/coverage/lcov-report/automations/index.html +20 -20
- package/coverage/lcov-report/automations/index.js.html +1 -1
- package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
- package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
- package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +32 -8
- package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +11 -11
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +5 -8
- package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
- package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
- package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
- package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/triggers.js.html +1 -1
- package/coverage/lcov-report/automations/utils.js.html +49 -16
- package/coverage/lcov-report/constants/index.html +1 -1
- package/coverage/lcov-report/constants/index.js.html +25 -25
- package/coverage/lcov-report/constants/layouts.js.html +1 -1
- package/coverage/lcov-report/constants/screens.js.html +2 -2
- package/coverage/lcov-report/db/client.js.html +19 -19
- package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
- package/coverage/lcov-report/db/index.html +15 -15
- package/coverage/lcov-report/db/index.js.html +3 -3
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
- package/coverage/lcov-report/db/newid.js.html +4 -4
- package/coverage/lcov-report/db/utils.js.html +108 -81
- package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
- package/coverage/lcov-report/events/index.html +1 -1
- package/coverage/lcov-report/events/index.js.html +1 -1
- package/coverage/lcov-report/events/utils.js.html +1 -1
- package/coverage/lcov-report/index.html +99 -84
- package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
- package/coverage/lcov-report/integrations/tests/index.html +1 -1
- package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
- package/coverage/lcov-report/middleware/authorized.js.html +12 -12
- package/coverage/lcov-report/middleware/builder.js.html +10 -10
- package/coverage/lcov-report/middleware/currentapp.js.html +48 -36
- package/coverage/lcov-report/middleware/index.html +1 -1
- package/coverage/lcov-report/middleware/joi-validator.js.html +11 -11
- package/coverage/lcov-report/middleware/resourceId.js.html +18 -18
- package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
- package/coverage/lcov-report/middleware/usageQuota.js.html +2 -2
- package/coverage/lcov-report/middleware/utils.js.html +2 -2
- package/coverage/lcov-report/threads/automation.js.html +3 -3
- package/coverage/lcov-report/threads/index.html +32 -32
- package/coverage/lcov-report/threads/index.js.html +12 -12
- package/coverage/lcov-report/threads/query.js.html +560 -65
- package/coverage/lcov-report/threads/utils.js.html +210 -15
- package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
- package/coverage/lcov-report/utilities/budibaseDir.js.html +2 -2
- package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
- package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
- package/coverage/lcov-report/utilities/global.js.html +28 -19
- package/coverage/lcov-report/utilities/index.html +19 -19
- package/coverage/lcov-report/utilities/index.js.html +70 -37
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +2 -2
- package/coverage/lcov-report/utilities/queue/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.html +19 -19
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +247 -10
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
- package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
- package/coverage/lcov-report/utilities/security.js.html +14 -5
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +1 -1
- package/coverage/lcov-report/utilities/workerRequests.js.html +22 -22
- package/coverage/lcov.info +2735 -2313
- package/dist/api/controllers/apikeys.js +2 -2
- package/dist/api/controllers/application.js +4 -4
- package/dist/api/controllers/auth.js +1 -1
- package/dist/api/controllers/automation.js +7 -5
- package/dist/api/controllers/cloud.js +2 -2
- package/dist/api/controllers/datasource.js +29 -0
- package/dist/api/controllers/deploy/index.js +2 -2
- package/dist/api/controllers/dev.js +2 -2
- package/dist/api/controllers/hosting.js +2 -2
- package/dist/api/controllers/permission.js +2 -2
- package/dist/api/controllers/query/import/index.js +79 -0
- package/dist/api/controllers/query/import/sources/base/index.js +64 -0
- package/dist/api/controllers/query/import/sources/base/openapi.js +42 -0
- package/dist/api/controllers/query/import/sources/curl.js +96 -0
- package/dist/api/controllers/query/import/sources/openapi2.js +142 -0
- package/dist/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
- package/dist/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
- package/dist/api/controllers/{query.js → query/index.js} +88 -56
- package/dist/api/controllers/query/validation.js +38 -0
- package/dist/api/controllers/role.js +1 -1
- package/dist/api/controllers/routing.js +1 -1
- package/dist/api/controllers/row/internal.js +14 -6
- package/dist/api/controllers/row/internalSearch.js +3 -2
- package/dist/api/controllers/row/utils.js +13 -6
- package/dist/api/controllers/screen.js +1 -1
- package/dist/api/controllers/user.js +40 -4
- package/dist/api/controllers/webhook.js +5 -1
- package/dist/api/index.js +1 -1
- package/dist/api/routes/apikeys.js +1 -1
- package/dist/api/routes/application.js +1 -1
- package/dist/api/routes/automation.js +1 -1
- package/dist/api/routes/backup.js +1 -1
- package/dist/api/routes/cloud.js +1 -1
- package/dist/api/routes/component.js +1 -1
- package/dist/api/routes/datasource.js +1 -1
- package/dist/api/routes/deploy.js +1 -1
- package/dist/api/routes/dev.js +1 -1
- package/dist/api/routes/hosting.js +1 -1
- package/dist/api/routes/integration.js +1 -1
- package/dist/api/routes/layout.js +1 -1
- package/dist/api/routes/metadata.js +1 -1
- package/dist/api/routes/permission.js +1 -1
- package/dist/api/routes/query.js +6 -34
- package/dist/api/routes/role.js +1 -1
- package/dist/api/routes/routing.js +1 -1
- package/dist/api/routes/row.js +1 -1
- package/dist/api/routes/screen.js +1 -1
- package/dist/api/routes/script.js +1 -1
- package/dist/api/routes/static.js +1 -1
- package/dist/api/routes/table.js +1 -1
- package/dist/api/routes/templates.js +1 -1
- package/dist/api/routes/tests/utilities/TestFunctions.js +1 -1
- package/dist/api/routes/user.js +4 -2
- package/dist/api/routes/view.js +1 -1
- package/dist/api/routes/webhook.js +1 -1
- package/dist/app.js +1 -1
- package/dist/automations/bullboard.js +1 -1
- package/dist/automations/steps/executeQuery.js +9 -2
- package/dist/automations/steps/outgoingWebhook.js +2 -3
- package/dist/automations/utils.js +11 -1
- package/dist/constants/index.js +3 -3
- package/dist/constants/screens.js +1 -1
- package/dist/db/client.js +1 -1
- package/dist/db/utils.js +9 -1
- package/dist/definitions/datasource.js +6 -1
- package/dist/integrations/base/sqlTable.js +1 -1
- package/dist/integrations/rest.js +259 -120
- package/dist/integrations/utils.js +40 -37
- package/dist/middleware/authorized.js +2 -2
- package/dist/middleware/builder.js +2 -2
- package/dist/middleware/currentapp.js +6 -6
- package/dist/middleware/usageQuota.js +1 -1
- package/dist/package.json +11 -4
- package/dist/tests/utilities/TestConfiguration.js +55 -8
- package/dist/tests/utilities/structures.js +2 -2
- package/dist/threads/automation.js +2 -2
- package/dist/threads/query.js +195 -38
- package/dist/threads/utils.js +62 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/budibaseDir.js +1 -1
- package/dist/utilities/fileSystem/utilities.js +2 -1
- package/dist/utilities/global.js +5 -5
- package/dist/utilities/index.js +11 -1
- package/dist/utilities/redis.js +1 -1
- package/dist/utilities/rowProcessor/index.js +76 -0
- package/dist/utilities/security.js +2 -2
- package/dist/utilities/usageQuota.js +2 -2
- package/dist/utilities/workerRequests.js +3 -3
- package/package.json +12 -5
- package/scripts/replicateApp.js +1 -1
- package/src/api/controllers/apikeys.js +2 -2
- package/src/api/controllers/application.js +7 -4
- package/src/api/controllers/auth.js +1 -1
- package/src/api/controllers/automation.js +8 -4
- package/src/api/controllers/cloud.js +5 -2
- package/src/api/controllers/datasource.js +34 -0
- package/src/api/controllers/deploy/index.js +2 -2
- package/src/api/controllers/dev.js +2 -2
- package/src/api/controllers/hosting.js +2 -2
- package/src/api/controllers/permission.js +2 -2
- package/src/api/controllers/query/import/index.ts +85 -0
- package/src/api/controllers/query/import/sources/base/index.ts +87 -0
- package/src/api/controllers/query/import/sources/base/openapi.ts +24 -0
- package/src/api/controllers/query/import/sources/curl.ts +102 -0
- package/src/api/controllers/query/import/sources/openapi2.ts +163 -0
- package/src/api/controllers/query/import/sources/tests/curl/curl.spec.js +103 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/delete.txt +1 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/empty-body.txt +2 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/get.txt +1 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/headers.txt +3 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/patch.txt +2 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/path.txt +1 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/post.txt +2 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/put.txt +2 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/query.txt +1 -0
- package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
- package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.yaml +160 -0
- package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
- package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.yaml +711 -0
- package/src/api/controllers/query/import/sources/tests/openapi2/openapi2.spec.js +238 -0
- package/src/api/controllers/query/import/tests/index.spec.js +109 -0
- package/src/api/controllers/query/index.js +196 -0
- package/src/api/controllers/query/validation.js +42 -0
- package/src/api/controllers/role.js +1 -1
- package/src/api/controllers/routing.js +1 -1
- package/src/api/controllers/row/internal.js +14 -5
- package/src/api/controllers/row/internalSearch.js +3 -2
- package/src/api/controllers/row/utils.js +11 -8
- package/src/api/controllers/screen.js +1 -1
- package/src/api/controllers/user.js +39 -3
- package/src/api/controllers/webhook.js +5 -1
- package/src/api/index.js +1 -1
- package/src/api/routes/apikeys.js +1 -1
- package/src/api/routes/application.js +1 -1
- package/src/api/routes/automation.js +1 -1
- package/src/api/routes/backup.js +1 -1
- package/src/api/routes/cloud.js +1 -1
- package/src/api/routes/component.js +1 -1
- package/src/api/routes/datasource.js +1 -1
- package/src/api/routes/deploy.js +1 -1
- package/src/api/routes/dev.js +1 -1
- package/src/api/routes/hosting.js +1 -1
- package/src/api/routes/integration.js +1 -1
- package/src/api/routes/layout.js +1 -1
- package/src/api/routes/metadata.js +1 -1
- package/src/api/routes/permission.js +4 -1
- package/src/api/routes/query.js +14 -36
- package/src/api/routes/role.js +1 -1
- package/src/api/routes/routing.js +1 -1
- package/src/api/routes/row.js +1 -1
- package/src/api/routes/screen.js +1 -1
- package/src/api/routes/script.js +1 -1
- package/src/api/routes/static.js +1 -1
- package/src/api/routes/table.js +1 -1
- package/src/api/routes/templates.js +1 -1
- package/src/api/routes/tests/datasource.spec.js +45 -0
- package/src/api/routes/tests/permissions.spec.js +1 -1
- package/src/api/routes/tests/query.spec.js +70 -1
- package/src/api/routes/tests/role.spec.js +2 -2
- package/src/api/routes/tests/routing.spec.js +1 -1
- package/src/api/routes/tests/user.spec.js +1 -1
- package/src/api/routes/tests/utilities/TestFunctions.js +1 -1
- package/src/api/routes/user.js +11 -1
- package/src/api/routes/view.js +1 -1
- package/src/api/routes/webhook.js +1 -1
- package/src/app.ts +1 -1
- package/src/automations/bullboard.js +1 -1
- package/src/automations/steps/executeQuery.js +10 -2
- package/src/automations/steps/outgoingWebhook.js +2 -3
- package/src/automations/utils.js +12 -1
- package/src/constants/index.js +3 -3
- package/src/constants/screens.js +1 -1
- package/src/db/client.js +1 -1
- package/src/db/utils.js +10 -1
- package/src/definitions/common.ts +2 -16
- package/src/definitions/datasource.ts +98 -1
- package/src/integrations/base/IntegrationBase.ts +4 -4
- package/src/integrations/base/sqlTable.ts +1 -1
- package/src/integrations/rest.ts +311 -138
- package/src/integrations/tests/rest.spec.js +432 -21
- package/src/integrations/utils.ts +8 -7
- package/src/middleware/authorized.js +2 -2
- package/src/middleware/builder.js +2 -2
- package/src/middleware/currentapp.js +11 -7
- package/src/middleware/tests/authorized.spec.js +2 -2
- package/src/middleware/tests/currentapp.spec.js +35 -41
- package/src/middleware/tests/usageQuota.spec.js +1 -1
- package/src/middleware/usageQuota.js +1 -1
- package/src/tests/utilities/TestConfiguration.js +65 -8
- package/src/tests/utilities/structures.js +2 -2
- package/src/threads/automation.js +2 -2
- package/src/threads/query.js +204 -39
- package/src/threads/utils.js +66 -1
- package/src/utilities/budibaseDir.js +1 -1
- package/src/utilities/fileSystem/utilities.js +3 -1
- package/src/utilities/global.js +8 -5
- package/src/utilities/index.js +12 -1
- package/src/utilities/redis.js +1 -1
- package/src/utilities/rowProcessor/index.js +79 -0
- package/src/utilities/security.js +5 -2
- package/src/utilities/usageQuota.js +2 -2
- package/src/utilities/workerRequests.js +3 -3
- package/builder/assets/index.9ac33cf1.js +0 -1316
- package/src/api/controllers/query.js +0 -161
|
@@ -0,0 +1,238 @@
|
|
|
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.name).toBe("Swagger Petstore")
|
|
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 init(file, extension)
|
|
61
|
+
const queries = await openapi2.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
|
+
},
|
|
122
|
+
"getEntity" : {
|
|
123
|
+
},
|
|
124
|
+
"updateEntity" : {
|
|
125
|
+
...contentTypeHeader
|
|
126
|
+
},
|
|
127
|
+
"patchEntity" : {
|
|
128
|
+
...contentTypeHeader
|
|
129
|
+
},
|
|
130
|
+
"deleteEntity" : {
|
|
131
|
+
"x-api-key" : "{{x-api-key}}",
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
await runTests("crud", testHeaders, assertions)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
const testQuery = async (file, extension, assertions) => {
|
|
139
|
+
const queries = await getQueries(file, extension)
|
|
140
|
+
for (let [operationId, queryString] of Object.entries(assertions)) {
|
|
141
|
+
expect(queries[operationId].fields.queryString).toStrictEqual(queryString)
|
|
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(JSON.stringify(body, null, 2))
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
it("populates body", async () => {
|
|
216
|
+
const assertions = {
|
|
217
|
+
"createEntity" : {
|
|
218
|
+
"name" : "name",
|
|
219
|
+
"type" : "type",
|
|
220
|
+
},
|
|
221
|
+
"getEntities" : undefined,
|
|
222
|
+
"getEntity" : undefined,
|
|
223
|
+
"updateEntity" : {
|
|
224
|
+
"id": 1,
|
|
225
|
+
"name" : "name",
|
|
226
|
+
"type" : "type",
|
|
227
|
+
},
|
|
228
|
+
"patchEntity" : {
|
|
229
|
+
"id": 1,
|
|
230
|
+
"name" : "name",
|
|
231
|
+
"type" : "type",
|
|
232
|
+
},
|
|
233
|
+
"deleteEntity" : undefined
|
|
234
|
+
}
|
|
235
|
+
await runTests("crud", testBody, assertions)
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
})
|
|
@@ -0,0 +1,109 @@
|
|
|
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
|
+
}
|
|
55
|
+
|
|
56
|
+
it("gets info", async () => {
|
|
57
|
+
const assertions = {
|
|
58
|
+
"oapi2CrudJson" : {
|
|
59
|
+
name: "CRUD",
|
|
60
|
+
},
|
|
61
|
+
"oapi2CrudYaml" : {
|
|
62
|
+
name: "CRUD",
|
|
63
|
+
},
|
|
64
|
+
"oapi2PetstoreJson" : {
|
|
65
|
+
name: "Swagger Petstore",
|
|
66
|
+
},
|
|
67
|
+
"oapi2PetstoreYaml" :{
|
|
68
|
+
name: "Swagger Petstore",
|
|
69
|
+
},
|
|
70
|
+
"curl": {
|
|
71
|
+
name: "example.com",
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
await runTest(testGetInfo, assertions)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const testImportQueries = async (key, data, assertions) => {
|
|
78
|
+
await init(data)
|
|
79
|
+
bulkDocs.mockReturnValue([])
|
|
80
|
+
const importResult = await restImporter.importQueries("appId", "datasourceId")
|
|
81
|
+
expect(importResult.errorQueries.length).toBe(0)
|
|
82
|
+
expect(importResult.queries.length).toBe(assertions[key].count)
|
|
83
|
+
expect(bulkDocs).toHaveBeenCalledTimes(1)
|
|
84
|
+
jest.clearAllMocks()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
it("imports queries", async () => {
|
|
88
|
+
// simple sanity assertions that the whole dataset
|
|
89
|
+
// makes it through the importer
|
|
90
|
+
const assertions = {
|
|
91
|
+
"oapi2CrudJson" : {
|
|
92
|
+
count: 6,
|
|
93
|
+
},
|
|
94
|
+
"oapi2CrudYaml" :{
|
|
95
|
+
count: 6,
|
|
96
|
+
},
|
|
97
|
+
"oapi2PetstoreJson" : {
|
|
98
|
+
count: 20,
|
|
99
|
+
},
|
|
100
|
+
"oapi2PetstoreYaml" :{
|
|
101
|
+
count: 20,
|
|
102
|
+
},
|
|
103
|
+
"curl": {
|
|
104
|
+
count: 1
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
await runTest(testImportQueries, assertions)
|
|
108
|
+
})
|
|
109
|
+
})
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const CouchDB = require("../../../db")
|
|
2
|
+
const {
|
|
3
|
+
generateQueryID,
|
|
4
|
+
getQueryParams,
|
|
5
|
+
isProdAppID,
|
|
6
|
+
} = require("../../../db/utils")
|
|
7
|
+
const { BaseQueryVerbs } = require("../../../constants")
|
|
8
|
+
const { Thread, ThreadType } = require("../../../threads")
|
|
9
|
+
const { save: saveDatasource } = require("../datasource")
|
|
10
|
+
const { RestImporter } = require("./import")
|
|
11
|
+
const { invalidateDynamicVariables } = require("../../../threads/utils")
|
|
12
|
+
|
|
13
|
+
const Runner = new Thread(ThreadType.QUERY, { timeoutMs: 10000 })
|
|
14
|
+
|
|
15
|
+
// simple function to append "readable" to all read queries
|
|
16
|
+
function enrichQueries(input) {
|
|
17
|
+
const wasArray = Array.isArray(input)
|
|
18
|
+
const queries = wasArray ? input : [input]
|
|
19
|
+
for (let query of queries) {
|
|
20
|
+
if (query.queryVerb === BaseQueryVerbs.READ) {
|
|
21
|
+
query.readable = true
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return wasArray ? queries : queries[0]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exports.fetch = async function (ctx) {
|
|
28
|
+
const db = new CouchDB(ctx.appId)
|
|
29
|
+
|
|
30
|
+
const body = await db.allDocs(
|
|
31
|
+
getQueryParams(null, {
|
|
32
|
+
include_docs: true,
|
|
33
|
+
})
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
ctx.body = enrichQueries(body.rows.map(row => row.doc))
|
|
37
|
+
}
|
|
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
|
+
|
|
78
|
+
exports.save = async function (ctx) {
|
|
79
|
+
const db = new CouchDB(ctx.appId)
|
|
80
|
+
const query = ctx.request.body
|
|
81
|
+
|
|
82
|
+
if (!query._id) {
|
|
83
|
+
query._id = generateQueryID(query.datasourceId)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const response = await db.put(query)
|
|
87
|
+
query._rev = response.rev
|
|
88
|
+
|
|
89
|
+
ctx.body = query
|
|
90
|
+
ctx.message = `Query ${query.name} saved successfully.`
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
exports.find = async function (ctx) {
|
|
94
|
+
const db = new CouchDB(ctx.appId)
|
|
95
|
+
const query = enrichQueries(await db.get(ctx.params.queryId))
|
|
96
|
+
// remove properties that could be dangerous in real app
|
|
97
|
+
if (isProdAppID(ctx.appId)) {
|
|
98
|
+
delete query.fields
|
|
99
|
+
delete query.parameters
|
|
100
|
+
}
|
|
101
|
+
ctx.body = query
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
exports.preview = async function (ctx) {
|
|
105
|
+
const db = new CouchDB(ctx.appId)
|
|
106
|
+
|
|
107
|
+
const datasource = await db.get(ctx.request.body.datasourceId)
|
|
108
|
+
// preview may not have a queryId as it hasn't been saved, but if it does
|
|
109
|
+
// this stops dynamic variables from calling the same query
|
|
110
|
+
const { fields, parameters, queryVerb, transformer, queryId } =
|
|
111
|
+
ctx.request.body
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const { rows, keys, info, extra } = await Runner.run({
|
|
115
|
+
appId: ctx.appId,
|
|
116
|
+
datasource,
|
|
117
|
+
queryVerb,
|
|
118
|
+
fields,
|
|
119
|
+
parameters,
|
|
120
|
+
transformer,
|
|
121
|
+
queryId,
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
ctx.body = {
|
|
125
|
+
rows,
|
|
126
|
+
schemaFields: [...new Set(keys)],
|
|
127
|
+
info,
|
|
128
|
+
extra,
|
|
129
|
+
}
|
|
130
|
+
} catch (err) {
|
|
131
|
+
ctx.throw(400, err)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function execute(ctx, opts = { rowsOnly: false }) {
|
|
136
|
+
const db = new CouchDB(ctx.appId)
|
|
137
|
+
|
|
138
|
+
const query = await db.get(ctx.params.queryId)
|
|
139
|
+
const datasource = await db.get(query.datasourceId)
|
|
140
|
+
|
|
141
|
+
// call the relevant CRUD method on the integration class
|
|
142
|
+
try {
|
|
143
|
+
const { rows, pagination, extra } = await Runner.run({
|
|
144
|
+
appId: ctx.appId,
|
|
145
|
+
datasource,
|
|
146
|
+
queryVerb: query.queryVerb,
|
|
147
|
+
fields: query.fields,
|
|
148
|
+
pagination: ctx.request.body.pagination,
|
|
149
|
+
parameters: ctx.request.body.parameters,
|
|
150
|
+
transformer: query.transformer,
|
|
151
|
+
queryId: ctx.params.queryId,
|
|
152
|
+
})
|
|
153
|
+
if (opts && opts.rowsOnly) {
|
|
154
|
+
ctx.body = rows
|
|
155
|
+
} else {
|
|
156
|
+
ctx.body = { data: rows, pagination, ...extra }
|
|
157
|
+
}
|
|
158
|
+
} catch (err) {
|
|
159
|
+
ctx.throw(400, err)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
exports.executeV1 = async function (ctx) {
|
|
164
|
+
return execute(ctx, { rowsOnly: true })
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
exports.executeV2 = async function (ctx) {
|
|
168
|
+
return execute(ctx, { rowsOnly: false })
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const removeDynamicVariables = async (db, queryId) => {
|
|
172
|
+
const query = await db.get(queryId)
|
|
173
|
+
const datasource = await db.get(query.datasourceId)
|
|
174
|
+
const dynamicVariables = datasource.config.dynamicVariables
|
|
175
|
+
|
|
176
|
+
if (dynamicVariables) {
|
|
177
|
+
// delete dynamic variables from the datasource
|
|
178
|
+
const newVariables = dynamicVariables.filter(dv => dv.queryId !== queryId)
|
|
179
|
+
datasource.config.dynamicVariables = newVariables
|
|
180
|
+
await db.put(datasource)
|
|
181
|
+
|
|
182
|
+
// invalidate the deleted variables
|
|
183
|
+
const variablesToDelete = dynamicVariables.filter(
|
|
184
|
+
dv => dv.queryId === queryId
|
|
185
|
+
)
|
|
186
|
+
await invalidateDynamicVariables(variablesToDelete)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
exports.destroy = async function (ctx) {
|
|
191
|
+
const db = new CouchDB(ctx.appId)
|
|
192
|
+
await removeDynamicVariables(db, ctx.params.queryId)
|
|
193
|
+
await db.remove(ctx.params.queryId, ctx.params.revId)
|
|
194
|
+
ctx.message = `Query deleted.`
|
|
195
|
+
ctx.status = 200
|
|
196
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
queryId: Joi.string().optional(),
|
|
41
|
+
}))
|
|
42
|
+
}
|
|
@@ -11,6 +11,7 @@ const {
|
|
|
11
11
|
inputProcessing,
|
|
12
12
|
outputProcessing,
|
|
13
13
|
processAutoColumn,
|
|
14
|
+
cleanupAttachments,
|
|
14
15
|
} = require("../../../utilities/rowProcessor")
|
|
15
16
|
const { FieldTypes } = require("../../../constants")
|
|
16
17
|
const { isEqual } = require("lodash")
|
|
@@ -25,6 +26,7 @@ const {
|
|
|
25
26
|
getFromDesignDoc,
|
|
26
27
|
getFromMemoryDoc,
|
|
27
28
|
} = require("../view/utils")
|
|
29
|
+
const { cloneDeep } = require("lodash/fp")
|
|
28
30
|
|
|
29
31
|
const CALCULATION_TYPES = {
|
|
30
32
|
SUM: "sum",
|
|
@@ -109,14 +111,14 @@ exports.patch = async ctx => {
|
|
|
109
111
|
const inputs = ctx.request.body
|
|
110
112
|
const tableId = inputs.tableId
|
|
111
113
|
const isUserTable = tableId === InternalTables.USER_METADATA
|
|
112
|
-
let
|
|
114
|
+
let oldRow
|
|
113
115
|
try {
|
|
114
|
-
|
|
116
|
+
oldRow = await db.get(inputs._id)
|
|
115
117
|
} catch (err) {
|
|
116
118
|
if (isUserTable) {
|
|
117
119
|
// don't include the rev, it'll be the global rev
|
|
118
120
|
// this time
|
|
119
|
-
|
|
121
|
+
oldRow = {
|
|
120
122
|
_id: inputs._id,
|
|
121
123
|
}
|
|
122
124
|
} else {
|
|
@@ -125,13 +127,14 @@ exports.patch = async ctx => {
|
|
|
125
127
|
}
|
|
126
128
|
let dbTable = await db.get(tableId)
|
|
127
129
|
// need to build up full patch fields before coerce
|
|
130
|
+
let combinedRow = cloneDeep(oldRow)
|
|
128
131
|
for (let key of Object.keys(inputs)) {
|
|
129
132
|
if (!dbTable.schema[key]) continue
|
|
130
|
-
|
|
133
|
+
combinedRow[key] = inputs[key]
|
|
131
134
|
}
|
|
132
135
|
|
|
133
136
|
// this returns the table and row incase they have been updated
|
|
134
|
-
let { table, row } = inputProcessing(ctx.user, dbTable,
|
|
137
|
+
let { table, row } = inputProcessing(ctx.user, dbTable, combinedRow)
|
|
135
138
|
const validateResult = await validate({
|
|
136
139
|
row,
|
|
137
140
|
table,
|
|
@@ -149,6 +152,8 @@ exports.patch = async ctx => {
|
|
|
149
152
|
tableId: row.tableId,
|
|
150
153
|
table,
|
|
151
154
|
})
|
|
155
|
+
// check if any attachments removed
|
|
156
|
+
await cleanupAttachments(appId, table, { oldRow, row })
|
|
152
157
|
|
|
153
158
|
if (isUserTable) {
|
|
154
159
|
// the row has been updated, need to put it into the ctx
|
|
@@ -295,6 +300,8 @@ exports.destroy = async function (ctx) {
|
|
|
295
300
|
row,
|
|
296
301
|
tableId: row.tableId,
|
|
297
302
|
})
|
|
303
|
+
// remove any attachments that were on the row from object storage
|
|
304
|
+
await cleanupAttachments(appId, table, { row })
|
|
298
305
|
|
|
299
306
|
let response
|
|
300
307
|
if (ctx.params.tableId === InternalTables.USER_METADATA) {
|
|
@@ -341,6 +348,8 @@ exports.bulkDestroy = async ctx => {
|
|
|
341
348
|
} else {
|
|
342
349
|
await db.bulkDocs(rows.map(row => ({ ...row, _deleted: true })))
|
|
343
350
|
}
|
|
351
|
+
// remove any attachments that were on the rows from object storage
|
|
352
|
+
await cleanupAttachments(appId, table, { rows })
|
|
344
353
|
await Promise.all(updates)
|
|
345
354
|
return { response: { ok: true }, rows }
|
|
346
355
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { SearchIndexes } = require("../../../db/utils")
|
|
2
2
|
const fetch = require("node-fetch")
|
|
3
|
-
const { getCouchUrl } = require("@budibase/
|
|
3
|
+
const { getCouchUrl } = require("@budibase/backend-core/db")
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Class to build lucene query URLs.
|
|
@@ -191,7 +191,8 @@ class QueryBuilder {
|
|
|
191
191
|
}
|
|
192
192
|
if (this.query.equal) {
|
|
193
193
|
build(this.query.equal, (key, value) => {
|
|
194
|
-
if
|
|
194
|
+
// 0 evaluates to false, which means we would return all rows if we don't check it
|
|
195
|
+
if (!value && value !== 0) {
|
|
195
196
|
return null
|
|
196
197
|
}
|
|
197
198
|
return `${key}:${builder.preprocess(value, allPreProcessingOpts)}`
|