Merge remote-tracking branch 'origin/develop' into feature/export-from-client

This commit is contained in:
Peter Clement 2022-03-08 13:56:56 +00:00
commit 38ba2509d7
22 changed files with 2860 additions and 107 deletions

View File

@ -49,7 +49,7 @@ http {
add_header X-Frame-Options SAMEORIGIN always; add_header X-Frame-Options SAMEORIGIN always;
add_header X-Content-Type-Options nosniff always; add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always; add_header X-XSS-Protection "1; mode=block" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.budi.live https://js.intercomcdn.com https://widget.intercom.io; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com https://rsms.me https://maxcdn.bootstrapcdn.com; object-src 'none'; base-uri 'self'; connect-src 'self' https://api-iam.intercom.io https://app.posthog.com wss://nexus-websocket-a.intercom.io; font-src 'self' data https://cdn.jsdelivr.net https://fonts.gstatic.com https://rsms.me https://maxcdn.bootstrapcdn.com; frame-src 'self' https:; img-src http: https: data; manifest-src 'self'; media-src 'self'; worker-src 'none';" always; add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.budi.live https://js.intercomcdn.com https://widget.intercom.io; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com https://rsms.me https://maxcdn.bootstrapcdn.com; object-src 'none'; base-uri 'self'; connect-src 'self' https://api-iam.intercom.io https://app.posthog.com wss://nexus-websocket-a.intercom.io ; font-src 'self' data https://cdn.jsdelivr.net https://fonts.gstatic.com https://rsms.me https://maxcdn.bootstrapcdn.com; frame-src 'self' https:; img-src http: https: data; manifest-src 'self'; media-src 'self'; worker-src 'none';" always;
# upstreams # upstreams
set $apps {{ apps }}; set $apps {{ apps }};

View File

@ -1,5 +1,5 @@
{ {
"version": "1.0.80-alpha.2", "version": "1.0.81-alpha.0",
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [
"packages/*" "packages/*"

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/backend-core", "name": "@budibase/backend-core",
"version": "1.0.80-alpha.2", "version": "1.0.81-alpha.0",
"description": "Budibase backend core libraries used in server and worker", "description": "Budibase backend core libraries used in server and worker",
"main": "src/index.js", "main": "src/index.js",
"author": "Budibase", "author": "Budibase",

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/bbui", "name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.", "description": "A UI solution used in the different Budibase projects.",
"version": "1.0.80-alpha.2", "version": "1.0.81-alpha.0",
"license": "MPL-2.0", "license": "MPL-2.0",
"svelte": "src/index.js", "svelte": "src/index.js",
"module": "dist/bbui.es.js", "module": "dist/bbui.es.js",
@ -38,7 +38,7 @@
], ],
"dependencies": { "dependencies": {
"@adobe/spectrum-css-workflow-icons": "^1.2.1", "@adobe/spectrum-css-workflow-icons": "^1.2.1",
"@budibase/string-templates": "^1.0.80-alpha.2", "@budibase/string-templates": "^1.0.81-alpha.0",
"@spectrum-css/actionbutton": "^1.0.1", "@spectrum-css/actionbutton": "^1.0.1",
"@spectrum-css/actiongroup": "^1.0.1", "@spectrum-css/actiongroup": "^1.0.1",
"@spectrum-css/avatar": "^3.0.2", "@spectrum-css/avatar": "^3.0.2",

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/builder", "name": "@budibase/builder",
"version": "1.0.80-alpha.2", "version": "1.0.81-alpha.0",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"scripts": { "scripts": {
@ -65,10 +65,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.0.80-alpha.2", "@budibase/bbui": "^1.0.81-alpha.0",
"@budibase/client": "^1.0.80-alpha.2", "@budibase/client": "^1.0.81-alpha.0",
"@budibase/frontend-core": "^1.0.80-alpha.2", "@budibase/frontend-core": "^1.0.81-alpha.0",
"@budibase/string-templates": "^1.0.80-alpha.2", "@budibase/string-templates": "^1.0.81-alpha.0",
"@sentry/browser": "5.19.1", "@sentry/browser": "5.19.1",
"@spectrum-css/page": "^3.0.1", "@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1", "@spectrum-css/vars": "^3.0.1",

View File

@ -20,7 +20,9 @@
$goto(`./datasource/${resp._id}`) $goto(`./datasource/${resp._id}`)
notifications.success(`Datasource updated successfully.`) notifications.success(`Datasource updated successfully.`)
} catch (err) { } catch (err) {
notifications.error("Error saving datasource") notifications.error(err?.message ?? "Error saving datasource")
// prevent the modal from closing
return false
} }
} }

View File

@ -134,8 +134,9 @@
// Remove all iframe event listeners on component destroy // Remove all iframe event listeners on component destroy
onDestroy(() => { onDestroy(() => {
window.removeEventListener("message", receiveMessage)
if (iframe.contentWindow) { if (iframe.contentWindow) {
window.removeEventListener("message", receiveMessage)
if (!$store.clientFeatures.messagePassing) { if (!$store.clientFeatures.messagePassing) {
// Legacy - remove in later versions of BB // Legacy - remove in later versions of BB
iframe.contentWindow.removeEventListener( iframe.contentWindow.removeEventListener(

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/cli", "name": "@budibase/cli",
"version": "1.0.80-alpha.2", "version": "1.0.81-alpha.0",
"description": "Budibase CLI, for developers, self hosting and migrations.", "description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "src/index.js", "main": "src/index.js",
"bin": { "bin": {

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/client", "name": "@budibase/client",
"version": "1.0.80-alpha.2", "version": "1.0.81-alpha.0",
"license": "MPL-2.0", "license": "MPL-2.0",
"module": "dist/budibase-client.js", "module": "dist/budibase-client.js",
"main": "dist/budibase-client.js", "main": "dist/budibase-client.js",
@ -19,26 +19,12 @@
"dev:builder": "rollup -cw" "dev:builder": "rollup -cw"
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.0.80-alpha.2", "@budibase/bbui": "^1.0.81-alpha.0",
"@budibase/frontend-core": "^1.0.80-alpha.2", "@budibase/frontend-core": "^1.0.81-alpha.0",
"@budibase/string-templates": "^1.0.80-alpha.2", "@budibase/string-templates": "^1.0.81-alpha.0",
"@spectrum-css/button": "^3.0.3",
"@spectrum-css/card": "^3.0.3",
"@spectrum-css/divider": "^1.0.3",
"@spectrum-css/link": "^3.1.3",
"@spectrum-css/page": "^3.0.1",
"@spectrum-css/tag": "^3.1.4",
"@spectrum-css/typography": "^3.0.2",
"@spectrum-css/vars": "^3.0.1",
"apexcharts": "^3.22.1",
"dayjs": "^1.10.5",
"downloadjs": "1.4.7",
"regexparam": "^1.3.0", "regexparam": "^1.3.0",
"rollup-plugin-polyfill-node": "^0.8.0", "rollup-plugin-polyfill-node": "^0.8.0",
"shortid": "^2.2.15", "shortid": "^2.2.15",
"svelte": "^3.38.2",
"svelte-apexcharts": "^1.0.2",
"svelte-flatpickr": "^3.1.0",
"svelte-spa-router": "^3.0.5" "svelte-spa-router": "^3.0.5"
}, },
"devDependencies": { "devDependencies": {

View File

@ -81,7 +81,10 @@
loading = false loading = false
return res return res
} catch (error) { } catch (error) {
notificationStore.actions.error(`Error uploading file: ${error}`) notificationStore.actions.error(
`Error uploading file: ${error?.message || error}`
)
loading = false
} }
} }

2689
packages/client/stats.html Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,12 +1,12 @@
{ {
"name": "@budibase/frontend-core", "name": "@budibase/frontend-core",
"version": "1.0.80-alpha.2", "version": "1.0.81-alpha.0",
"description": "Budibase frontend core libraries used in builder and client", "description": "Budibase frontend core libraries used in builder and client",
"author": "Budibase", "author": "Budibase",
"license": "MPL-2.0", "license": "MPL-2.0",
"svelte": "src/index.js", "svelte": "src/index.js",
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.0.80-alpha.2", "@budibase/bbui": "^1.0.81-alpha.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"svelte": "^3.46.2" "svelte": "^3.46.2"
} }

View File

@ -1,61 +1,66 @@
export const buildAttachmentEndpoints = API => ({ export const buildAttachmentEndpoints = API => {
/**
* Uploads an attachment to the server.
* @param data the attachment to upload
* @param tableId the table ID to upload to
*/
uploadAttachment: async ({ data, tableId }) => {
return await API.post({
url: `/api/attachments/${tableId}/upload`,
body: data,
json: false,
})
},
/**
* Uploads an attachment to the server as a builder user from the builder.
* @param data the data to upload
*/
uploadBuilderAttachment: async data => {
return await API.post({
url: "/api/attachments/process",
body: data,
json: false,
})
},
/** /**
* Generates a signed URL to upload a file to an external datasource. * Generates a signed URL to upload a file to an external datasource.
* @param datasourceId the ID of the datasource to upload to * @param datasourceId the ID of the datasource to upload to
* @param bucket the name of the bucket to upload to * @param bucket the name of the bucket to upload to
* @param key the name of the file to upload to * @param key the name of the file to upload to
*/ */
getSignedDatasourceURL: async ({ datasourceId, bucket, key }) => { const getSignedDatasourceURL = async ({ datasourceId, bucket, key }) => {
return await API.post({ return await API.post({
url: `/api/attachments/${datasourceId}/url`, url: `/api/attachments/${datasourceId}/url`,
body: { bucket, key }, body: { bucket, key },
}) })
}, }
/** return {
* Uploads a file to an external datasource. getSignedDatasourceURL,
* @param datasourceId the ID of the datasource to upload to
* @param bucket the name of the bucket to upload to /**
* @param key the name of the file to upload to * Uploads an attachment to the server.
* @param data the file to upload * @param data the attachment to upload
*/ * @param tableId the table ID to upload to
externalUpload: async ({ datasourceId, bucket, key, data }) => { */
const { signedUrl, publicUrl } = await API.getSignedDatasourceURL({ uploadAttachment: async ({ data, tableId }) => {
datasourceId, return await API.post({
bucket, url: `/api/attachments/${tableId}/upload`,
key, body: data,
}) json: false,
await API.put({ })
url: signedUrl, },
body: data,
json: false, /**
external: true, * Uploads an attachment to the server as a builder user from the builder.
}) * @param data the data to upload
return { publicUrl } */
}, uploadBuilderAttachment: async data => {
}) return await API.post({
url: "/api/attachments/process",
body: data,
json: false,
})
},
/**
* Uploads a file to an external datasource.
* @param datasourceId the ID of the datasource to upload to
* @param bucket the name of the bucket to upload to
* @param key the name of the file to upload to
* @param data the file to upload
*/
externalUpload: async ({ datasourceId, bucket, key, data }) => {
console.log(API)
const { signedUrl, publicUrl } = await getSignedDatasourceURL({
datasourceId,
bucket,
key,
})
await API.put({
url: signedUrl,
body: data,
json: false,
external: true,
})
return { publicUrl }
},
}
}

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/server", "name": "@budibase/server",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "1.0.80-alpha.2", "version": "1.0.81-alpha.0",
"description": "Budibase Web Server", "description": "Budibase Web Server",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -71,9 +71,9 @@
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@apidevtools/swagger-parser": "^10.0.3", "@apidevtools/swagger-parser": "^10.0.3",
"@budibase/backend-core": "^1.0.80-alpha.2", "@budibase/backend-core": "^1.0.81-alpha.0",
"@budibase/client": "^1.0.80-alpha.2", "@budibase/client": "^1.0.81-alpha.0",
"@budibase/string-templates": "^1.0.80-alpha.2", "@budibase/string-templates": "^1.0.81-alpha.0",
"@bull-board/api": "^3.7.0", "@bull-board/api": "^3.7.0",
"@bull-board/koa": "^3.7.0", "@bull-board/koa": "^3.7.0",
"@elastic/elasticsearch": "7.10.0", "@elastic/elasticsearch": "7.10.0",

View File

@ -17,12 +17,23 @@ const options = {
}, },
servers: [ servers: [
{ {
url: "http://budibase.app/api/public/v1", url: "https://budibase.app/api/public/v1",
description: "Budibase Cloud API", description: "Budibase Cloud API",
}, },
{ {
url: "{protocol}://{hostname}:10000/api/public/v1", url: "{protocol}://{hostname}/api/public/v1",
description: "Budibase self hosted API", description: "Budibase self hosted API",
variables: {
protocol: {
default: "http",
description:
"Whether HTTP or HTTPS should be used to communicate with your Budibase instance.",
},
hostname: {
default: "localhost:10000",
description: "The URL of your Budibase instance.",
},
},
}, },
], ],
components: { components: {

View File

@ -7,12 +7,22 @@
}, },
"servers": [ "servers": [
{ {
"url": "http://budibase.app/api/public/v1", "url": "https://budibase.app/api/public/v1",
"description": "Budibase Cloud API" "description": "Budibase Cloud API"
}, },
{ {
"url": "{protocol}://{hostname}:10000/api/public/v1", "url": "{protocol}://{hostname}/api/public/v1",
"description": "Budibase self hosted API" "description": "Budibase self hosted API",
"variables": {
"protocol": {
"default": "http",
"description": "Whether HTTP or HTTPS should be used to communicate with your Budibase instance."
},
"hostname": {
"default": "localhost:10000",
"description": "The URL of your Budibase instance."
}
}
} }
], ],
"components": { "components": {

View File

@ -4,10 +4,18 @@ info:
description: The public API for Budibase apps and its services. description: The public API for Budibase apps and its services.
version: 1.0.0 version: 1.0.0
servers: servers:
- url: http://budibase.app/api/public/v1 - url: https://budibase.app/api/public/v1
description: Budibase Cloud API description: Budibase Cloud API
- url: "{protocol}://{hostname}:10000/api/public/v1" - url: "{protocol}://{hostname}/api/public/v1"
description: Budibase self hosted API description: Budibase self hosted API
variables:
protocol:
default: http
description: Whether HTTP or HTTPS should be used to communicate with your
Budibase instance.
hostname:
default: localhost:10000
description: The URL of your Budibase instance.
components: components:
parameters: parameters:
tableId: tableId:

View File

@ -25,7 +25,8 @@ async function makeTableRequest(
operation, operation,
table, table,
tables, tables,
oldTable = null oldTable = null,
renamed = null
) { ) {
const json = { const json = {
endpoint: { endpoint: {
@ -41,6 +42,9 @@ async function makeTableRequest(
if (oldTable) { if (oldTable) {
json.meta.table = oldTable json.meta.table = oldTable
} }
if (renamed) {
json.meta.renamed = renamed
}
return makeExternalQuery(datasource, json) return makeExternalQuery(datasource, json)
} }
@ -160,6 +164,7 @@ function isRelationshipSetup(column) {
exports.save = async function (ctx) { exports.save = async function (ctx) {
const table = ctx.request.body const table = ctx.request.body
const { _rename: renamed } = table
// can't do this right now // can't do this right now
delete table.dataImport delete table.dataImport
const datasourceId = getDatasourceId(ctx.request.body) const datasourceId = getDatasourceId(ctx.request.body)
@ -241,7 +246,14 @@ exports.save = async function (ctx) {
const operation = oldTable const operation = oldTable
? DataSourceOperation.UPDATE_TABLE ? DataSourceOperation.UPDATE_TABLE
: DataSourceOperation.CREATE_TABLE : DataSourceOperation.CREATE_TABLE
await makeTableRequest(datasource, operation, tableToSave, tables, oldTable) await makeTableRequest(
datasource,
operation,
tableToSave,
tables,
oldTable,
renamed
)
// update any extra tables (like foreign keys in other tables) // update any extra tables (like foreign keys in other tables)
for (let extraTable of extraTablesToUpdate) { for (let extraTable of extraTablesToUpdate) {
const oldExtraTable = oldTables[extraTable.name] const oldExtraTable = oldTables[extraTable.name]
@ -258,6 +270,8 @@ exports.save = async function (ctx) {
) )
} }
// remove the rename prop
delete tableToSave._rename
// store it into couch now for budibase reference // store it into couch now for budibase reference
datasource.entities[tableToSave.name] = tableToSave datasource.entities[tableToSave.name] = tableToSave
await db.put(datasource) await db.put(datasource)

View File

@ -138,6 +138,11 @@ export interface PaginationJson {
page?: string | number page?: string | number
} }
export interface RenameColumn {
old: string
updated: string
}
export interface RelationshipsJson { export interface RelationshipsJson {
through?: string through?: string
from?: string from?: string
@ -166,6 +171,7 @@ export interface QueryJson {
meta?: { meta?: {
table?: Table table?: Table
tables?: Record<string, Table> tables?: Record<string, Table>
renamed: RenameColumn
} }
extra?: { extra?: {
idFilter?: SearchFilters idFilter?: SearchFilters

View File

@ -1,6 +1,10 @@
import { Knex, knex } from "knex" import { Knex, knex } from "knex"
import { Table } from "../../definitions/common" import { Table } from "../../definitions/common"
import { Operation, QueryJson } from "../../definitions/datasource" import {
Operation,
QueryJson,
RenameColumn,
} from "../../definitions/datasource"
import { breakExternalTableId } from "../utils" import { breakExternalTableId } from "../utils"
import SchemaBuilder = Knex.SchemaBuilder import SchemaBuilder = Knex.SchemaBuilder
import CreateTableBuilder = Knex.CreateTableBuilder import CreateTableBuilder = Knex.CreateTableBuilder
@ -10,7 +14,8 @@ function generateSchema(
schema: CreateTableBuilder, schema: CreateTableBuilder,
table: Table, table: Table,
tables: Record<string, Table>, tables: Record<string, Table>,
oldTable: null | Table = null oldTable: null | Table = null,
renamed?: RenameColumn
) { ) {
let primaryKey = table && table.primary ? table.primary[0] : null let primaryKey = table && table.primary ? table.primary[0] : null
const columns = Object.values(table.schema) const columns = Object.values(table.schema)
@ -29,7 +34,11 @@ function generateSchema(
for (let [key, column] of Object.entries(table.schema)) { for (let [key, column] of Object.entries(table.schema)) {
// skip things that are already correct // skip things that are already correct
const oldColumn = oldTable ? oldTable.schema[key] : null const oldColumn = oldTable ? oldTable.schema[key] : null
if ((oldColumn && oldColumn.type) || (primaryKey === key && !isJunction)) { if (
(oldColumn && oldColumn.type) ||
(primaryKey === key && !isJunction) ||
renamed?.updated === key
) {
continue continue
} }
switch (column.type) { switch (column.type) {
@ -81,6 +90,10 @@ function generateSchema(
} }
} }
if (renamed) {
schema.renameColumn(renamed.old, renamed.updated)
}
// need to check if any columns have been deleted // need to check if any columns have been deleted
if (oldTable) { if (oldTable) {
const deletedColumns = Object.entries(oldTable.schema) const deletedColumns = Object.entries(oldTable.schema)
@ -90,6 +103,9 @@ function generateSchema(
) )
.map(([key]) => key) .map(([key]) => key)
deletedColumns.forEach(key => { deletedColumns.forEach(key => {
if (renamed?.old === key) {
return
}
if (oldTable.constrained && oldTable.constrained.indexOf(key) !== -1) { if (oldTable.constrained && oldTable.constrained.indexOf(key) !== -1) {
schema.dropForeign(key) schema.dropForeign(key)
} }
@ -114,10 +130,11 @@ function buildUpdateTable(
knex: SchemaBuilder, knex: SchemaBuilder,
table: Table, table: Table,
tables: Record<string, Table>, tables: Record<string, Table>,
oldTable: Table oldTable: Table,
renamed: RenameColumn
): SchemaBuilder { ): SchemaBuilder {
return knex.alterTable(table.name, schema => { return knex.alterTable(table.name, schema => {
generateSchema(schema, table, tables, oldTable) generateSchema(schema, table, tables, oldTable, renamed)
}) })
} }
@ -167,7 +184,8 @@ class SqlTableQueryBuilder {
client, client,
json.table, json.table,
json.meta.tables, json.meta.tables,
json.meta.table json.meta.table,
json.meta.renamed
) )
break break
case Operation.DELETE_TABLE: case Operation.DELETE_TABLE:

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/string-templates", "name": "@budibase/string-templates",
"version": "1.0.80-alpha.2", "version": "1.0.81-alpha.0",
"description": "Handlebars wrapper for Budibase templating.", "description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs", "main": "src/index.cjs",
"module": "dist/bundle.mjs", "module": "dist/bundle.mjs",

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/worker", "name": "@budibase/worker",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "1.0.80-alpha.2", "version": "1.0.81-alpha.0",
"description": "Budibase background service", "description": "Budibase background service",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -34,8 +34,8 @@
"author": "Budibase", "author": "Budibase",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@budibase/backend-core": "^1.0.80-alpha.2", "@budibase/backend-core": "^1.0.81-alpha.0",
"@budibase/string-templates": "^1.0.80-alpha.2", "@budibase/string-templates": "^1.0.81-alpha.0",
"@koa/router": "^8.0.0", "@koa/router": "^8.0.0",
"@sentry/node": "^6.0.0", "@sentry/node": "^6.0.0",
"@techpass/passport-openidconnect": "^0.3.0", "@techpass/passport-openidconnect": "^0.3.0",