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,25 +126,27 @@
<header> <header>
<Heading small>{query.name}</Heading> <Heading small>{query.name}</Heading>
<div class="queryVerbs"> {#if config}
{#each QueryVerb as queryVerb} <div class="queryVerbs">
<div {#each Object.keys(config) as queryVerb}
class="queryVerb" <div
class:selected={queryVerb === query.queryVerb} class="queryVerb"
on:click={() => { class:selected={queryVerb === query.queryVerb}
query.queryVerb = queryVerb on:click={() => {
}}> query.queryVerb = queryVerb
{queryVerb} }}>
</div> {queryVerb}
{/each} </div>
</div>
{#if config && query.queryVerb}
<Select thin secondary bind:value={query.queryType}>
<option value={''}>Select an option</option>
{#each Object.keys(config[query.queryVerb]) as queryType}
<option value={queryType}>{queryType}</option>
{/each} {/each}
</Select> </div>
{#if query.queryVerb}
<Select thin secondary bind:value={query.queryType}>
<option value={''}>Select an option</option>
{#each Object.keys(config[query.queryVerb]) as queryType}
<option value={queryType}>{queryType}</option>
{/each}
</Select>
{/if}
{/if} {/if}
</header> </header>

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,19 +24,21 @@
<Heading extraSmall black>Query</Heading> <Heading extraSmall black>Query</Heading>
<Spacer large /> <Spacer large />
{#if schema.type === QueryTypes.SQL} {#if schema}
<Editor {#if schema.type === QueryTypes.SQL}
label="Query" <Editor
mode="sql" label="Query"
on:change={updateQuery} mode="sql"
value={query.fields.sql} /> on:change={updateQuery}
{:else if schema.type === QueryTypes.JSON} value={query.fields.sql} />
<Spacer large /> {:else if schema.type === QueryTypes.JSON}
<Editor <Spacer large />
label="Query" <Editor
mode="json" label="Query"
on:change={updateQuery} mode="json"
value={query.fields.json} /> on:change={updateQuery}
{:else if schema.type === QueryTypes.FIELDS} value={query.fields.json} />
<FieldsBuilder bind:fields={query.fields} {schema} /> {:else if schema.type === QueryTypes.FIELDS}
<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,28 +1,36 @@
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: {
type: "sql", SQL: {
type: "sql",
},
},
read: {
SQL: {
type: "sql",
},
}, },
}, },
} }
@ -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,8 +17,15 @@ const SCHEMA = {
}, },
}, },
query: { query: {
JSON: { create: {
type: "json", JSON: {
type: "json",
},
},
read: {
JSON: {
type: "json",
},
}, },
}, },
} }
@ -27,23 +34,35 @@ 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: "string", type: "password",
required: true, required: true,
}, },
}, },
query: {}, query: {
read: {
Bucket: {
type: "fields",
fields: {
bucket: {
type: "string",
required: true,
},
},
},
},
},
} }
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