From c6b1ea9a0fd69ff1d4d24708332fe2d670be3595 Mon Sep 17 00:00:00 2001 From: Christo Date: Thu, 8 Jul 2021 14:38:49 +0200 Subject: [PATCH] Feat: Add collection fields as "extra" query config for MongoDB --- .../integration/ExtraQueryConfig.svelte | 48 +++++++ .../components/integration/QueryViewer.svelte | 17 +++ packages/server/src/api/routes/query.js | 2 + packages/server/src/definitions/datasource.ts | 10 ++ packages/server/src/integrations/mongodb.ts | 125 ++++++++++++++++-- 5 files changed, 191 insertions(+), 11 deletions(-) create mode 100644 packages/builder/src/components/integration/ExtraQueryConfig.svelte diff --git a/packages/builder/src/components/integration/ExtraQueryConfig.svelte b/packages/builder/src/components/integration/ExtraQueryConfig.svelte new file mode 100644 index 0000000000..303beb1e4b --- /dev/null +++ b/packages/builder/src/components/integration/ExtraQueryConfig.svelte @@ -0,0 +1,48 @@ + + +{#each extraFields as { key, displayName, type }} +
+ + {#if type === "string"} + populateExtraQuery(extraQueryFields)} + bind:value={extraQueryFields[key]} + /> + {/if} + + {#if type === "list"} + queryConfig[verb]?.displayName || capitalise(verb)} />
+ {#if integrationInfo?.extra && query.queryVerb} + + {/if} {/if} diff --git a/packages/server/src/api/routes/query.js b/packages/server/src/api/routes/query.js index dd307c9444..2bbadcb40a 100644 --- a/packages/server/src/api/routes/query.js +++ b/packages/server/src/api/routes/query.js @@ -30,6 +30,7 @@ function generateQueryValidation() { default: Joi.string().allow(""), })), queryVerb: Joi.string().allow().required(), + extra: Joi.object().optional(), schema: Joi.object({}).required().unknown(true) })) } @@ -39,6 +40,7 @@ function generateQueryPreviewValidation() { return joiValidator.body(Joi.object({ fields: Joi.object().required(), queryVerb: Joi.string().allow().required(), + extra: Joi.object().optional(), datasourceId: Joi.string().required(), parameters: Joi.object({}).required().unknown(true) })) diff --git a/packages/server/src/definitions/datasource.ts b/packages/server/src/definitions/datasource.ts index 22f1998601..24d8144940 100644 --- a/packages/server/src/definitions/datasource.ts +++ b/packages/server/src/definitions/datasource.ts @@ -49,6 +49,15 @@ export interface QueryDefinition { urlDisplay?: boolean } +export interface ExtraQueryConfig { + [key: string]: { + displayName: string, + type: string, + required: boolean + data?: object + } +} + export interface Integration { docs: string plus?: boolean @@ -58,6 +67,7 @@ export interface Integration { query: { [key: string]: QueryDefinition } + extra?: ExtraQueryConfig } export interface SearchFilters { diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index af7b49153d..ab21da6fd0 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -10,7 +10,7 @@ module MongoDBModule { interface MongoDBConfig { connectionString: string db: string - collection: string + // collection: string } const SCHEMA: Integration = { @@ -28,10 +28,6 @@ module MongoDBModule { type: DatasourceFieldTypes.STRING, required: true, }, - collection: { - type: DatasourceFieldTypes.STRING, - required: true, - }, }, query: { create: { @@ -40,7 +36,31 @@ module MongoDBModule { read: { type: QueryTypes.JSON, }, + update: { + type: QueryTypes.JSON, + }, + delete: { + type: QueryTypes.JSON, + } }, + extra: { + collection: { + displayName: "Collection", + type: DatasourceFieldTypes.STRING, + required: true, + }, + actionTypes: { + displayName: "Action Types", + type: DatasourceFieldTypes.LIST, + required: true, + data: { + read: ['find', 'findOne', 'findOneAndUpdate', "count", "distinct"], + create: ['insertOne', 'insertMany'], + update: ['updateOne', 'updateMany'], + delete: ['deleteOne', 'deleteMany'] + } + } + } } class MongoIntegration { @@ -56,12 +76,25 @@ module MongoDBModule { return this.client.connect() } - async create(query: { json: object }) { + async create(query: { json: object, extra: { [key: string]: string } }) { try { await this.connect() const db = this.client.db(this.config.db) - const collection = db.collection(this.config.collection) - return collection.insertOne(query.json) + const collection = db.collection(query.extra.collection) + + // For mongodb we add an extra actionType to specify + // which method we want to call on the collection + switch(query.extra.actionTypes) { + case 'insertOne': { + return collection.insertOne(query.json) + } + case 'insertMany': { + return collection.insertOne(query.json).toArray() + } + default: { + throw new Error(`actionType ${query.extra.actionTypes} does not exist on DB for create`) + } + } } catch (err) { console.error("Error writing to mongodb", err) throw err @@ -70,12 +103,32 @@ module MongoDBModule { } } - async read(query: { json: object }) { + async read(query: { json: object, extra: { [key: string]: string } }) { try { await this.connect() const db = this.client.db(this.config.db) - const collection = db.collection(this.config.collection) - return collection.find(query.json).toArray() + const collection = db.collection(query.extra.collection) + + switch(query.extra.actionTypes) { + case 'find': { + return collection.find(query.json).toArray() + } + case 'findOne': { + return collection.findOne(query.json) + } + case 'findOneAndUpdate': { + return collection.findOneAndUpdate(query.json) + } + case 'count': { + return collection.countDocuments(query.json) + } + case 'distinct': { + return collection.distinct(query.json) + } + default: { + throw new Error(`actionType ${query.extra.actionTypes} does not exist on DB for read`) + } + } } catch (err) { console.error("Error querying mongodb", err) throw err @@ -83,6 +136,56 @@ module MongoDBModule { await this.client.close() } } + + async update(query: { json: object, extra: { [key: string]: string } }) { + try { + await this.connect() + const db = this.client.db(this.config.db) + const collection = db.collection(query.extra.collection) + + switch(query.extra.actionTypes) { + case 'updateOne': { + return collection.updateOne(query.json) + } + case 'updateMany': { + return collection.updateMany(query.json).toArray() + } + default: { + throw new Error(`actionType ${query.extra.actionTypes} does not exist on DB for update`) + } + } + } catch (err) { + console.error("Error writing to mongodb", err) + throw err + } finally { + await this.client.close() + } + } + + async delete(query: { json: object, extra: { [key: string]: string } }) { + try { + await this.connect() + const db = this.client.db(this.config.db) + const collection = db.collection(query.extra.collection) + + switch(query.extra.actionTypes) { + case 'deleteOne': { + return collection.deleteOne(query.json) + } + case 'deleteMany': { + return collection.deleteMany(query.json).toArray() + } + default: { + throw new Error(`actionType ${query.extra.actionTypes} does not exist on DB for delete`) + } + } + } catch (err) { + console.error("Error writing to mongodb", err) + throw err + } finally { + await this.client.close() + } + } } module.exports = {