From cf3c5dccd0690480baea17fa3937e5e2f079d475 Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Wed, 5 Jan 2022 10:29:40 -0500 Subject: [PATCH 1/8] Fix auth dropdown z-index --- packages/bbui/src/Tabs/Tabs.svelte | 7 ++++++- .../[selectedDatasource]/rest/[query]/index.svelte | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/bbui/src/Tabs/Tabs.svelte b/packages/bbui/src/Tabs/Tabs.svelte index c68f715de0..b587636f55 100644 --- a/packages/bbui/src/Tabs/Tabs.svelte +++ b/packages/bbui/src/Tabs/Tabs.svelte @@ -10,6 +10,8 @@ export let noHorizPadding = false export let quiet = false export let emphasized = false + // overlay content from the tab bar onto tabs e.g. for a dropdown + export let onTop = false let thisSelected = undefined @@ -78,6 +80,7 @@ 'spectrum-Tabs--quiet'} spectrum-Tabs--{vertical ? 'vertical' : 'horizontal'}" + class:onTop > {#if $tab.info} @@ -98,7 +101,9 @@ .quiet { border-bottom: none !important; } - + .onTop { + z-index: 1; + } .spectrum-Tabs { padding-left: var(--spacing-xl); padding-right: var(--spacing-xl); diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte index 43037242f3..3af4fd2c48 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte @@ -306,7 +306,7 @@ - + Create dynamic variables based on response body or headers - from other queries. + from this query. Date: Wed, 5 Jan 2022 10:31:06 -0500 Subject: [PATCH 2/8] Add full URL to path for imported queries --- .../controllers/query/import/sources/base/index.ts | 4 +++- .../api/controllers/query/import/sources/curl.ts | 10 +++++++--- .../controllers/query/import/sources/openapi2.ts | 14 +++++++++----- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/packages/server/src/api/controllers/query/import/sources/base/index.ts b/packages/server/src/api/controllers/query/import/sources/base/index.ts index 06e8dcfeff..e666fdc193 100644 --- a/packages/server/src/api/controllers/query/import/sources/base/index.ts +++ b/packages/server/src/api/controllers/query/import/sources/base/index.ts @@ -1,7 +1,7 @@ import { Query, QueryParameter } from "../../../../../../definitions/datasource" +import { URL } from "url" export interface ImportInfo { - url: string name: string } @@ -23,6 +23,7 @@ export abstract class ImportSource { name: string, method: string, path: string, + url: URL, queryString: string, headers: object = {}, parameters: QueryParameter[] = [], @@ -33,6 +34,7 @@ export abstract class ImportSource { const transformer = "return data" const schema = {} path = this.processPath(path) + path = `${url.origin}/${path}` queryString = this.processQuery(queryString) const requestBody = JSON.stringify(body, null, 2) diff --git a/packages/server/src/api/controllers/query/import/sources/curl.ts b/packages/server/src/api/controllers/query/import/sources/curl.ts index b55d24403b..d72441ab12 100644 --- a/packages/server/src/api/controllers/query/import/sources/curl.ts +++ b/packages/server/src/api/controllers/query/import/sources/curl.ts @@ -60,16 +60,19 @@ export class Curl extends ImportSource { return true } + getUrl = (): URL => { + return new URL(this.curl.raw_url) + } + getInfo = async (): Promise => { - const url = new URL(this.curl.url) + const url = this.getUrl() return { - url: url.origin, name: url.hostname, } } getQueries = async (datasourceId: string): Promise => { - const url = new URL(this.curl.raw_url) + const url = this.getUrl() const name = url.pathname const path = url.pathname const method = this.curl.method @@ -87,6 +90,7 @@ export class Curl extends ImportSource { name, method, path, + url, queryString, headers, [], diff --git a/packages/server/src/api/controllers/query/import/sources/openapi2.ts b/packages/server/src/api/controllers/query/import/sources/openapi2.ts index 35dab163f6..b079db21e8 100644 --- a/packages/server/src/api/controllers/query/import/sources/openapi2.ts +++ b/packages/server/src/api/controllers/query/import/sources/openapi2.ts @@ -2,6 +2,7 @@ import { ImportInfo } from "./base" import { Query, QueryParameter } from "../../../../../definitions/datasource" import { OpenAPIV2 } from "openapi-types" import { OpenAPISource } from "./base/openapi" +import { URL } from "url" const parameterNotRef = ( param: OpenAPIV2.Parameter | OpenAPIV2.ReferenceObject @@ -55,20 +56,22 @@ export class OpenAPI2 extends OpenAPISource { } } - getInfo = async (): Promise => { + getUrl = (): URL => { const scheme = this.document.schemes?.includes("https") ? "https" : "http" const basePath = this.document.basePath || "" const host = this.document.host || "" - const url = `${scheme}://${host}${basePath}` - const name = this.document.info.title || "Swagger Import" + return new URL(`${scheme}://${host}${basePath}`) + } + getInfo = async (): Promise => { + const name = this.document.info.title || "Swagger Import" return { - url: url, - name: name, + name } } getQueries = async (datasourceId: string): Promise => { + const url = this.getUrl() const queries = [] for (let [path, pathItem] of Object.entries(this.document.paths)) { @@ -145,6 +148,7 @@ export class OpenAPI2 extends OpenAPISource { name, methodName, path, + url, queryString, headers, parameters, From d7bf178dfdfdad144022b0e17526dde5dbab8e71 Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Wed, 5 Jan 2022 10:31:44 -0500 Subject: [PATCH 3/8] Fix Add Authentication button icon --- .../rest/auth/RestAuthenticationBuilder.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/rest/auth/RestAuthenticationBuilder.svelte b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/rest/auth/RestAuthenticationBuilder.svelte index 6c68e055e4..7bbd2402f0 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/rest/auth/RestAuthenticationBuilder.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/rest/auth/RestAuthenticationBuilder.svelte @@ -58,7 +58,7 @@ /> {/if}
- openConfigModal()} con="Add" + openConfigModal()} icon="Add" >Add authentication
From 6f53b25116568a4928158a3f265fb329c6e8568e Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Wed, 5 Jan 2022 11:54:59 -0500 Subject: [PATCH 4/8] Delete and invalidate linked dynamic variables when a query is deleted --- .../query/import/sources/openapi2.ts | 2 +- .../server/src/api/controllers/query/index.js | 21 +++++++++++++++++++ packages/server/src/threads/utils.js | 3 ++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/server/src/api/controllers/query/import/sources/openapi2.ts b/packages/server/src/api/controllers/query/import/sources/openapi2.ts index b079db21e8..c193654909 100644 --- a/packages/server/src/api/controllers/query/import/sources/openapi2.ts +++ b/packages/server/src/api/controllers/query/import/sources/openapi2.ts @@ -66,7 +66,7 @@ export class OpenAPI2 extends OpenAPISource { getInfo = async (): Promise => { const name = this.document.info.title || "Swagger Import" return { - name + name, } } diff --git a/packages/server/src/api/controllers/query/index.js b/packages/server/src/api/controllers/query/index.js index 6001b81aa9..ea2042ad49 100644 --- a/packages/server/src/api/controllers/query/index.js +++ b/packages/server/src/api/controllers/query/index.js @@ -8,6 +8,7 @@ const { BaseQueryVerbs } = require("../../../constants") const { Thread, ThreadType } = require("../../../threads") const { save: saveDatasource } = require("../datasource") const { RestImporter } = require("./import") +const { invalidateDynamicVariables } = require("../../../threads/utils") const Runner = new Thread(ThreadType.QUERY, { timeoutMs: 10000 }) @@ -166,8 +167,28 @@ exports.executeV2 = async function (ctx) { return execute(ctx, { rowsOnly: false }) } +const removeDynamicVariables = async (db, queryId) => { + const query = await db.get(queryId) + const datasource = await db.get(query.datasourceId) + const dynamicVariables = datasource.config.dynamicVariables + + if (dynamicVariables) { + // invalidate the deleted variables + const variablesToDelete = dynamicVariables.filter( + dv => dv.queryId === queryId + ) + await invalidateDynamicVariables(variablesToDelete) + + // delete dynamic variables from the datasource + const newVariables = dynamicVariables.filter(dv => dv.queryId !== queryId) + datasource.config.dynamicVariables = newVariables + await db.put(datasource) + } +} + exports.destroy = async function (ctx) { const db = new CouchDB(ctx.appId) + await removeDynamicVariables(db, ctx.params.queryId) await db.remove(ctx.params.queryId, ctx.params.revId) ctx.message = `Query deleted.` ctx.status = 200 diff --git a/packages/server/src/threads/utils.js b/packages/server/src/threads/utils.js index ffea596abd..e989d5cb63 100644 --- a/packages/server/src/threads/utils.js +++ b/packages/server/src/threads/utils.js @@ -42,10 +42,11 @@ exports.checkCacheForDynamicVariable = async (queryId, variable) => { } exports.invalidateDynamicVariables = async cachedVars => { + const cache = await getClient() let promises = [] for (let variable of cachedVars) { promises.push( - client.delete(makeVariableKey(variable.queryId, variable.name)) + cache.delete(makeVariableKey(variable.queryId, variable.name)) ) } await Promise.all(promises) From e45ee07192cfd1dcc522d8ecc3e1a0c869857058 Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Wed, 5 Jan 2022 13:27:15 -0500 Subject: [PATCH 5/8] Navigation fixes for duplicate and delete query --- .../DatasourceNavigator.svelte | 2 +- .../popovers/EditQueryPopover.svelte | 15 +++++++++++---- packages/builder/src/stores/backend/queries.js | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte index 18143c2071..af345ddcdf 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte @@ -137,7 +137,7 @@ selected={$queries.selected === query._id} on:click={() => onClickQuery(query)} > - + {/each} {/if} diff --git a/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte b/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte index 4e38dba11d..b15746735b 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/popovers/EditQueryPopover.svelte @@ -5,22 +5,29 @@ import { datasources, queries } from "stores/backend" export let query + export let onClickQuery let confirmDeleteDialog async function deleteQuery() { const wasSelectedQuery = $queries.selected - const selectedDatasource = $datasources.selected + // need to calculate this before the query is deleted + const navigateToDatasource = wasSelectedQuery === query._id + await queries.delete(query) - if (wasSelectedQuery === query._id) { - $goto(`./datasource/${selectedDatasource}`) + await datasources.fetch() + + if (navigateToDatasource) { + await datasources.select(query.datasourceId) + $goto(`./datasource/${query.datasourceId}`) } notifications.success("Query deleted") } async function duplicateQuery() { try { - await queries.duplicate(query) + const newQuery = await queries.duplicate(query) + onClickQuery(newQuery) } catch (e) { notifications.error(e.message) } diff --git a/packages/builder/src/stores/backend/queries.js b/packages/builder/src/stores/backend/queries.js index 0e767fa5c0..2018933ffc 100644 --- a/packages/builder/src/stores/backend/queries.js +++ b/packages/builder/src/stores/backend/queries.js @@ -134,7 +134,7 @@ export function createQueriesStore() { list.map(q => q.name) ) - actions.save(datasourceId, newQuery) + return actions.save(datasourceId, newQuery) }, } From 5c56abdadf4aefe09a37e5750f98809950972935 Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Wed, 5 Jan 2022 14:33:14 -0500 Subject: [PATCH 6/8] Support variables in URL --- .../[selectedDatasource]/rest/[query]/index.svelte | 8 ++++++-- packages/server/src/integrations/rest.ts | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte index 3af4fd2c48..c0e3bcea5e 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/rest/[query]/index.svelte @@ -232,8 +232,12 @@ const datasourceUrl = datasource?.config.url const qs = query?.fields.queryString breakQs = restUtils.breakQueryString(qs) - if (datasourceUrl && !query.fields.path?.startsWith(datasourceUrl)) { - const path = query.fields.path + const path = query.fields.path + if ( + datasourceUrl && + !path?.startsWith("http") && + !path?.startsWith("{{") // don't substitute the datasource url when query starts with a variable e.g. the upgrade path + ) { query.fields.path = `${datasource.config.url}/${path ? path : ""}` } url = buildUrl(query.fields.path, breakQs) diff --git a/packages/server/src/integrations/rest.ts b/packages/server/src/integrations/rest.ts index 63d7795a6d..06b4d327da 100644 --- a/packages/server/src/integrations/rest.ts +++ b/packages/server/src/integrations/rest.ts @@ -171,7 +171,7 @@ module RestModule { getUrl(path: string, queryString: string): string { const main = `${path}?${queryString}` let complete = main - if (this.config.url && !main.startsWith(this.config.url)) { + if (this.config.url && !main.startsWith("http")) { complete = !this.config.url ? main : `${this.config.url}/${main}` } if (!complete.startsWith("http")) { From 06114d948169fd67ea8c1decb0774c2a6d23422b Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Wed, 5 Jan 2022 14:49:01 -0500 Subject: [PATCH 7/8] Fix rest import tests for url and invert dynamic variable invalidation / deletion --- .../query/import/sources/tests/curl/curl.spec.js | 5 ++--- .../import/sources/tests/openapi2/openapi2.spec.js | 13 ++++++------- .../controllers/query/import/tests/index.spec.js | 6 ------ packages/server/src/api/controllers/query/index.js | 10 +++++----- 4 files changed, 13 insertions(+), 21 deletions(-) diff --git a/packages/server/src/api/controllers/query/import/sources/tests/curl/curl.spec.js b/packages/server/src/api/controllers/query/import/sources/tests/curl/curl.spec.js index 11869862f7..2b17685f24 100644 --- a/packages/server/src/api/controllers/query/import/sources/tests/curl/curl.spec.js +++ b/packages/server/src/api/controllers/query/import/sources/tests/curl/curl.spec.js @@ -35,7 +35,6 @@ describe("Curl Import", () => { it("returns import info", async () => { await init("get") const info = await curl.getInfo() - expect(info.url).toBe("http://example.com") expect(info.name).toBe("example.com") }) @@ -67,8 +66,8 @@ describe("Curl Import", () => { } it("populates path", async () => { - await testPath("get", "") - await testPath("path", "paths/abc") + await testPath("get", "http://example.com/") + await testPath("path", "http://example.com/paths/abc") }) const testHeaders = async (file, headers) => { diff --git a/packages/server/src/api/controllers/query/import/sources/tests/openapi2/openapi2.spec.js b/packages/server/src/api/controllers/query/import/sources/tests/openapi2/openapi2.spec.js index 845c4f38f6..3c5aa89e3c 100644 --- a/packages/server/src/api/controllers/query/import/sources/tests/openapi2/openapi2.spec.js +++ b/packages/server/src/api/controllers/query/import/sources/tests/openapi2/openapi2.spec.js @@ -41,7 +41,6 @@ describe("OpenAPI2 Import", () => { const testImportInfo = async (file, extension) => { await init(file, extension) const info = await openapi2.getInfo() - expect(info.url).toBe("https://petstore.swagger.io/v2") expect(info.name).toBe("Swagger Petstore") } @@ -92,12 +91,12 @@ describe("OpenAPI2 Import", () => { it("populates path", async () => { const assertions = { - "createEntity" : "entities", - "getEntities" : "entities", - "getEntity" : "entities/{{entityId}}", - "updateEntity" : "entities/{{entityId}}", - "patchEntity" : "entities/{{entityId}}", - "deleteEntity" : "entities/{{entityId}}" + "createEntity" : "http://example.com/entities", + "getEntities" : "http://example.com/entities", + "getEntity" : "http://example.com/entities/{{entityId}}", + "updateEntity" : "http://example.com/entities/{{entityId}}", + "patchEntity" : "http://example.com/entities/{{entityId}}", + "deleteEntity" : "http://example.com/entities/{{entityId}}" } await runTests("crud", testPath, assertions) }) diff --git a/packages/server/src/api/controllers/query/import/tests/index.spec.js b/packages/server/src/api/controllers/query/import/tests/index.spec.js index 32f3b43b44..5a509d2258 100644 --- a/packages/server/src/api/controllers/query/import/tests/index.spec.js +++ b/packages/server/src/api/controllers/query/import/tests/index.spec.js @@ -51,30 +51,24 @@ describe("Rest Importer", () => { await init(data) const info = await restImporter.getInfo() expect(info.name).toBe(assertions[key].name) - expect(info.url).toBe(assertions[key].url) } it("gets info", async () => { const assertions = { "oapi2CrudJson" : { name: "CRUD", - url: "http://example.com" }, "oapi2CrudYaml" : { name: "CRUD", - url: "http://example.com" }, "oapi2PetstoreJson" : { name: "Swagger Petstore", - url: "https://petstore.swagger.io/v2" }, "oapi2PetstoreYaml" :{ name: "Swagger Petstore", - url: "https://petstore.swagger.io/v2" }, "curl": { name: "example.com", - url: "http://example.com" } } await runTest(testGetInfo, assertions) diff --git a/packages/server/src/api/controllers/query/index.js b/packages/server/src/api/controllers/query/index.js index ea2042ad49..6e5fdfb356 100644 --- a/packages/server/src/api/controllers/query/index.js +++ b/packages/server/src/api/controllers/query/index.js @@ -173,16 +173,16 @@ const removeDynamicVariables = async (db, queryId) => { const dynamicVariables = datasource.config.dynamicVariables if (dynamicVariables) { + // delete dynamic variables from the datasource + const newVariables = dynamicVariables.filter(dv => dv.queryId !== queryId) + datasource.config.dynamicVariables = newVariables + await db.put(datasource) + // invalidate the deleted variables const variablesToDelete = dynamicVariables.filter( dv => dv.queryId === queryId ) await invalidateDynamicVariables(variablesToDelete) - - // delete dynamic variables from the datasource - const newVariables = dynamicVariables.filter(dv => dv.queryId !== queryId) - datasource.config.dynamicVariables = newVariables - await db.put(datasource) } } From c0006b4d8f6ff1d5d03734d71a5b94e57d84db60 Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Mon, 10 Jan 2022 11:50:08 +0000 Subject: [PATCH 8/8] Bump z-index to always be on top --- packages/bbui/src/Tabs/Tabs.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bbui/src/Tabs/Tabs.svelte b/packages/bbui/src/Tabs/Tabs.svelte index b587636f55..40e02058c1 100644 --- a/packages/bbui/src/Tabs/Tabs.svelte +++ b/packages/bbui/src/Tabs/Tabs.svelte @@ -102,7 +102,7 @@ border-bottom: none !important; } .onTop { - z-index: 1; + z-index: 20; } .spectrum-Tabs { padding-left: var(--spacing-xl);