schema updates, custom fields

This commit is contained in:
Martin McKeaveney 2021-01-13 16:39:47 +00:00
parent 94ee5855a5
commit 01ff661f17
12 changed files with 170 additions and 124 deletions

View File

@ -8,7 +8,7 @@
{#each Object.keys(integration) as configKey} {#each Object.keys(integration) as configKey}
<Input <Input
thin thin
type={configKey.type} type={integration[configKey].type}
label={configKey} label={configKey}
bind:value={integration[configKey]} /> bind:value={integration[configKey]} />
<Spacer medium /> <Spacer medium />

View File

@ -35,6 +35,7 @@
<Spacer medium /> <Spacer medium />
{/each} {/each}
{#if schema.customisable} {#if schema.customisable}
<Spacer large />
<Label>Add Custom Field</Label> <Label>Add Custom Field</Label>
{#each Object.keys(customSchema) as field} {#each Object.keys(customSchema) as field}
<Label extraSmall grey>{field}</Label> <Label extraSmall grey>{field}</Label>
@ -54,7 +55,7 @@
<option value={"number"}>Number</option> <option value={"number"}>Number</option>
</Select> </Select>
</div> </div>
<Button small thin primary on:click={addField}>Add Field</Button> <Button small thin secondary on:click={addField}>Add Field</Button>
{/if} {/if}
</form> </form>

View File

@ -32,8 +32,6 @@
}, },
] ]
const QueryVerb = ["create", "read", "update", "delete"]
export let query export let query
export let fields = [] export let fields = []
@ -128,8 +126,9 @@
<header> <header>
<Heading small>{query.name}</Heading> <Heading small>{query.name}</Heading>
{#if config}
<div class="queryVerbs"> <div class="queryVerbs">
{#each QueryVerb as queryVerb} {#each Object.keys(config) as queryVerb}
<div <div
class="queryVerb" class="queryVerb"
class:selected={queryVerb === query.queryVerb} class:selected={queryVerb === query.queryVerb}
@ -140,7 +139,7 @@
</div> </div>
{/each} {/each}
</div> </div>
{#if config && query.queryVerb} {#if query.queryVerb}
<Select thin secondary bind:value={query.queryType}> <Select thin secondary bind:value={query.queryType}>
<option value={''}>Select an option</option> <option value={''}>Select an option</option>
{#each Object.keys(config[query.queryVerb]) as queryType} {#each Object.keys(config[query.queryVerb]) as queryType}
@ -148,6 +147,7 @@
{/each} {/each}
</Select> </Select>
{/if} {/if}
{/if}
</header> </header>
<Spacer large /> <Spacer large />

View File

@ -14,7 +14,7 @@
export let schema export let schema
function updateQuery({ detail }) { function updateQuery({ detail }) {
query.fields.sql = detail.value query.fields[schema.type] = detail.value
} }
</script> </script>
@ -24,6 +24,7 @@
<Heading extraSmall black>Query</Heading> <Heading extraSmall black>Query</Heading>
<Spacer large /> <Spacer large />
{#if schema}
{#if schema.type === QueryTypes.SQL} {#if schema.type === QueryTypes.SQL}
<Editor <Editor
label="Query" label="Query"
@ -40,3 +41,4 @@
{:else if schema.type === QueryTypes.FIELDS} {:else if schema.type === QueryTypes.FIELDS}
<FieldsBuilder bind:fields={query.fields} {schema} /> <FieldsBuilder bind:fields={query.fields} {schema} />
{/if} {/if}
{/if}

View File

@ -26,9 +26,7 @@
<IntegrationConfigForm integration={datasource.config} /> <IntegrationConfigForm integration={datasource.config} />
<Spacer medium /> <Spacer medium />
<footer> <footer>
<Button primary wide disabled={false} on:click={saveDatasource}> <Button blue wide on:click={saveDatasource}>Save</Button>
Save
</Button>
</footer> </footer>
</section> </section>
{/if} {/if}

View File

@ -1,7 +1,12 @@
class Field { exports.QUERY_TYPES = {
constructor(type, defaultValue, required) { SQL: "sql",
this.type = type JSON: "json",
this.default = defaultValue FIELDS: "fields",
this.required = required
} }
exports.FIELD_TYPES = {
STRING: "string",
NUMBER: "number",
PASSWORD: "password",
LIST: "list",
} }

View File

@ -1,14 +1,15 @@
const Airtable = require("airtable") const Airtable = require("airtable")
const { FIELD_TYPES, QUERY_TYPES } = require("./Integration")
const SCHEMA = { const SCHEMA = {
datasource: { datasource: {
apiKey: { apiKey: {
type: "string", type: FIELD_TYPES.STRING,
default: "enter api key", default: "enter api key",
required: true, required: true,
}, },
base: { base: {
type: "string", type: FIELD_TYPES.STRING,
default: "mybase", default: "mybase",
required: true, required: true,
}, },
@ -20,7 +21,7 @@ const SCHEMA = {
customisable: true, customisable: true,
fields: { fields: {
table: { table: {
type: "string", type: FIELD_TYPES.STRING,
required: true, required: true,
}, },
}, },
@ -28,14 +29,14 @@ const SCHEMA = {
}, },
read: { read: {
Table: { Table: {
type: "fields", type: QUERY_TYPES.FIELDS,
fields: { fields: {
table: { table: {
type: "string", type: FIELD_TYPES.STRING,
required: true, required: true,
}, },
view: { view: {
type: "string", type: FIELD_TYPES.STRING,
required: true, required: true,
}, },
}, },
@ -43,11 +44,11 @@ const SCHEMA = {
}, },
update: { update: {
Fields: { Fields: {
type: "fields", type: QUERY_TYPES.FIELDS,
customisable: true, customisable: true,
fields: { fields: {
id: { id: {
type: "string", type: FIELD_TYPES.STRING,
required: true, required: true,
}, },
}, },
@ -55,7 +56,7 @@ const SCHEMA = {
}, },
delete: { delete: {
"Airtable Ids": { "Airtable Ids": {
type: "list", type: FIELD_TYPES.LIST,
}, },
}, },
}, },

View File

@ -1,53 +1,46 @@
const AWS = require("aws-sdk") const AWS = require("aws-sdk")
const { FIELD_TYPES, QUERY_TYPES } = require("./Integration")
const SCHEMA = { const SCHEMA = {
datasource: { datasource: {
table: {
type: "string",
required: true,
},
region: { region: {
type: "string", type: FIELD_TYPES.STRING,
required: true, required: true,
default: "us-east-1", default: "us-east-1",
}, },
accessKeyId: { accessKeyId: {
type: "string", type: FIELD_TYPES.PASSWORD,
required: true, required: true,
}, },
secretKey: { secretKey: {
type: "secretKey", type: FIELD_TYPES.PASSWORD,
required: true, required: true,
default: 5432,
},
indexName: {
type: "string",
}, },
}, },
query: { query: {
type: "fields", read: {
fields: [ DynamoConfig: {
{ type: QUERY_TYPES.FIELDS,
name: "Index", fields: {
key: "Index", Table: {
type: "string", type: FIELD_TYPES.STRING,
required: true,
},
Index: {
type: FIELD_TYPES.STRING,
},
KeyConditionExpression: {
type: FIELD_TYPES.STRING,
},
ExpressionAttributeNames: {
type: FIELD_TYPES.STRING,
},
ExpressionAttributeValues: {
type: FIELD_TYPES.STRING,
}, },
{
name: "Key Condition Expression",
key: "KeyConditionExpression",
type: "string",
}, },
{
name: "Attribute Names",
key: "ExpressionAttributeNames",
type: "string",
}, },
{
name: "Attribute Values",
key: "ExpressionAttributeValues",
type: "string",
}, },
],
}, },
} }
@ -62,12 +55,12 @@ class DynamoDBIntegration {
AWS.config.update(this.config) AWS.config.update(this.config)
} }
async read() { async read(query) {
const response = await this.client.query({ const response = await this.client.query({
TableName: this.config.table, TableName: query.Table,
KeyConditionExpression: this.config.KeyConditionExpression, KeyConditionExpression: query.KeyConditionExpression,
ExpressionAttributeNames: this.config.ExpressionAttributeNames, ExpressionAttributeNames: query.ExpressionAttributeNames,
ExpressionAttributeValues: this.config.ExpressionAttributeValues, ExpressionAttributeValues: query.ExpressionAttributeValues,
}) })
return response return response
} }

View File

@ -26,11 +26,11 @@ class ElasticSearchIntegration {
this.client = new Client({ node: config.url }) this.client = new Client({ node: config.url })
} }
async create(document) { async create(query) {
try { try {
const result = await this.client.index({ const result = await this.client.index({
index: this.config.index, index: this.config.index,
body: JSON.parse(document), body: JSON.parse(query.json),
}) })
return [result] return [result]
} catch (err) { } catch (err) {
@ -45,7 +45,7 @@ class ElasticSearchIntegration {
try { try {
const result = await this.client.search({ const result = await this.client.search({
index: this.config.index, index: this.config.index,
body: JSON.parse(query), body: JSON.parse(query.json),
}) })
return result.body.hits.hits.map(({ _source }) => _source) return result.body.hits.hits.map(({ _source }) => _source)
} catch (err) { } catch (err) {

View File

@ -1,30 +1,38 @@
const sqlServer = require("mssql") const sqlServer = require("mssql")
const { FIELD_TYPES } = require("./Integration")
const SCHEMA = { const SCHEMA = {
datasource: { datasource: {
user: { user: {
type: "string", type: FIELD_TYPES.STRING,
required: true, required: true,
default: "localhost", default: "localhost",
}, },
password: { password: {
type: "password", type: FIELD_TYPES.PASSWORD,
required: true, required: true,
}, },
server: { server: {
type: "string", type: FIELD_TYPES.STRING,
default: "localhost", default: "localhost",
}, },
database: { database: {
type: "string", type: FIELD_TYPES.STRING,
default: "root", default: "root",
}, },
}, },
query: { query: {
sql: { create: {
SQL: {
type: "sql", type: "sql",
}, },
}, },
read: {
SQL: {
type: "sql",
},
},
},
} }
class SqlServerIntegration { class SqlServerIntegration {
@ -37,10 +45,21 @@ class SqlServerIntegration {
return await this.client.connect(this.config) return await this.client.connect(this.config)
} }
async read() { async read(query) {
try { try {
await this.connect() await this.connect()
const response = await this.client.query(this.config.query) const response = await this.client.query(query.sql)
return response.recordset
} catch (err) {
console.error("Error querying MS SQL Server", err)
throw err
}
}
async create(query) {
try {
await this.connect()
const response = await this.client.query(query.sql)
return response.recordset return response.recordset
} catch (err) { } catch (err) {
console.error("Error querying MS SQL Server", err) console.error("Error querying MS SQL Server", err)

View File

@ -17,33 +17,52 @@ const SCHEMA = {
}, },
}, },
query: { query: {
create: {
JSON: { JSON: {
type: "json", type: "json",
}, },
}, },
read: {
JSON: {
type: "json",
},
},
},
} }
class MongoIntegration { class MongoIntegration {
constructor(config) { constructor(config) {
this.config = config this.config = config
this.client = new MongoClient(config.connectionString) this.client = new MongoClient(config.connectionString)
try {
this.config.query = JSON.parse(this.config.query)
} catch (err) {
this.config.query = {}
}
this.connect()
} }
async connect() { async connect() {
return this.client.connect() return this.client.connect()
} }
async read() { async create(query) {
try { try {
const mongoQuery = query.json ? JSON.parse(query.json) : {}
await this.connect()
const db = this.client.db(this.config.db) const db = this.client.db(this.config.db)
const collection = db.collection(this.config.collection) const collection = db.collection(this.config.collection)
const result = await collection.find(this.config.query).toArray() const result = await collection.insertOne(mongoQuery)
return result
} catch (err) {
console.error("Error querying mongodb", err)
throw err
} finally {
await this.client.close()
}
}
async read(query) {
try {
const mongoQuery = query.json ? JSON.parse(query.json) : {}
await this.connect()
const db = this.client.db(this.config.db)
const collection = db.collection(this.config.collection)
const result = await collection.find(mongoQuery).toArray()
return result return result
} catch (err) { } catch (err) {
console.error("Error querying mongodb", err) console.error("Error querying mongodb", err)

View File

@ -2,25 +2,33 @@ const AWS = require("aws-sdk")
const SCHEMA = { const SCHEMA = {
datasource: { datasource: {
bucket: {
type: "string",
required: true,
},
region: { region: {
type: "string", type: "string",
required: true, required: true,
default: "us-east-1", default: "us-east-1",
}, },
accessKeyId: { accessKeyId: {
type: "string", type: "password",
required: true, required: true,
}, },
secretAccessKey: { secretAccessKey: {
type: "password",
required: true,
},
},
query: {
read: {
Bucket: {
type: "fields",
fields: {
bucket: {
type: "string", type: "string",
required: true, required: true,
}, },
}, },
query: {}, },
},
},
} }
class S3Integration { class S3Integration {
@ -34,10 +42,10 @@ class S3Integration {
AWS.config.update(this.config) AWS.config.update(this.config)
} }
async query() { async read(query) {
const response = await this.client const response = await this.client
.listObjects({ .listObjects({
Bucket: this.config.bucket, Bucket: query.bucket,
}) })
.promise() .promise()
return response.Contents return response.Contents