diff --git a/lerna.json b/lerna.json index 05183ad6d4..caae7fbaaa 100644 --- a/lerna.json +++ b/lerna.json @@ -7,6 +7,7 @@ "packages/account-portal/packages/*" ], "useNx": true, + "concurrency": 20, "command": { "publish": { "ignoreChanges": [ @@ -21,4 +22,4 @@ "loadEnvFiles": false } } -} \ No newline at end of file +} diff --git a/packages/builder/src/components/backend/DataTable/buttons/ExistingRelationshipButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/ExistingRelationshipButton.svelte index 839c396614..03f210e528 100644 --- a/packages/builder/src/components/backend/DataTable/buttons/ExistingRelationshipButton.svelte +++ b/packages/builder/src/components/backend/DataTable/buttons/ExistingRelationshipButton.svelte @@ -1,14 +1,19 @@ diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index c9010c0c1a..936eb614d6 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -85,6 +85,7 @@ let relationshipTableIdSecondary = null let table = $tables.selected + let confirmDeleteDialog let savingColumn let deleteColName diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/_components/panels/Relationships.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/_components/panels/Relationships.svelte index 1a46ecb540..19f2486298 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/_components/panels/Relationships.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/_components/panels/Relationships.svelte @@ -15,7 +15,8 @@ let modal - $: tables = Object.values(datasource.entities) + $: tables = + $tablesStore.list.filter(tbl => tbl.sourceId === datasource._id) || [] $: relationships = getRelationships(tables) function getRelationships(tables) { @@ -43,14 +44,16 @@ }) }) - return Object.values(relatedColumns).map(({ from, to, through }) => { - return { - tables: `${from.tableName} ${through ? "↔" : "→"} ${to.tableName}`, - columns: `${from.name} to ${to.name}`, - from, - to, - } - }) + return Object.values(relatedColumns) + .filter(({ from, to }) => from && to) + .map(({ from, to, through }) => { + return { + tables: `${from.tableName} ${through ? "↔" : "→"} ${to.tableName}`, + columns: `${from.name} to ${to.name}`, + from, + to, + } + }) } const handleRowClick = ({ detail }) => { diff --git a/packages/server/src/api/controllers/datasource.ts b/packages/server/src/api/controllers/datasource.ts index 39bc612b32..0a7430aa94 100644 --- a/packages/server/src/api/controllers/datasource.ts +++ b/packages/server/src/api/controllers/datasource.ts @@ -26,6 +26,7 @@ import { import sdk from "../../sdk" import { builderSocket } from "../../websockets" import { setupCreationAuth as googleSetupCreationAuth } from "../../integrations/googlesheets" +import { isEqual } from "lodash" async function getConnector( datasource: Datasource @@ -198,19 +199,20 @@ async function invalidateVariables( export async function update(ctx: UserCtx) { const db = context.getAppDB() const datasourceId = ctx.params.datasourceId - let datasource = await sdk.datasources.get(datasourceId) - const auth = datasource.config?.auth - await invalidateVariables(datasource, ctx.request.body) + const baseDatasource = await sdk.datasources.get(datasourceId) + const auth = baseDatasource.config?.auth + await invalidateVariables(baseDatasource, ctx.request.body) - const isBudibaseSource = datasource.type === dbCore.BUDIBASE_DATASOURCE_TYPE + const isBudibaseSource = + baseDatasource.type === dbCore.BUDIBASE_DATASOURCE_TYPE const dataSourceBody = isBudibaseSource ? { name: ctx.request.body?.name } : ctx.request.body - datasource = { - ...datasource, - ...sdk.datasources.mergeConfigs(dataSourceBody, datasource), + let datasource: Datasource = { + ...baseDatasource, + ...sdk.datasources.mergeConfigs(dataSourceBody, baseDatasource), } if (auth && !ctx.request.body.auth) { // don't strip auth config from DB @@ -245,6 +247,15 @@ export async function update(ctx: UserCtx) { datasource: await sdk.datasources.removeSecretSingle(datasource), } builderSocket?.emitDatasourceUpdate(ctx, datasource) + // send table updates if they have occurred + if (datasource.entities) { + for (let table of Object.values(datasource.entities)) { + const oldTable = baseDatasource.entities?.[table.name] + if (!oldTable || !isEqual(oldTable, table)) { + builderSocket?.emitTableUpdate(ctx, table, { includeOriginator: true }) + } + } + } } const preSaveAction: Partial> = { diff --git a/packages/server/src/integrations/base/sqlTable.ts b/packages/server/src/integrations/base/sqlTable.ts index 05954f0d25..1d3f542a10 100644 --- a/packages/server/src/integrations/base/sqlTable.ts +++ b/packages/server/src/integrations/base/sqlTable.ts @@ -6,13 +6,19 @@ import { QueryJson, RenameColumn, Table, + FieldType, } from "@budibase/types" import { breakExternalTableId } from "../utils" import SchemaBuilder = Knex.SchemaBuilder import CreateTableBuilder = Knex.CreateTableBuilder -import { FieldTypes, RelationshipType } from "../../constants" +import { RelationshipType } from "../../constants" import { utils } from "@budibase/shared-core" +function isIgnoredType(type: FieldType) { + const ignored = [FieldType.LINK, FieldType.FORMULA] + return ignored.indexOf(type) !== -1 +} + function generateSchema( schema: CreateTableBuilder, table: Table, @@ -47,13 +53,13 @@ function generateSchema( continue } switch (column.type) { - case FieldTypes.STRING: - case FieldTypes.OPTIONS: - case FieldTypes.LONGFORM: - case FieldTypes.BARCODEQR: + case FieldType.STRING: + case FieldType.OPTIONS: + case FieldType.LONGFORM: + case FieldType.BARCODEQR: schema.text(key) break - case FieldTypes.BB_REFERENCE: + case FieldType.BB_REFERENCE: const subtype = column.subtype as FieldSubtype switch (subtype) { case FieldSubtype.USER: @@ -66,7 +72,7 @@ function generateSchema( throw utils.unreachable(subtype) } break - case FieldTypes.NUMBER: + case FieldType.NUMBER: // if meta is specified then this is a junction table entry if (column.meta && column.meta.toKey && column.meta.toTable) { const { toKey, toTable } = column.meta @@ -76,21 +82,21 @@ function generateSchema( schema.float(key) } break - case FieldTypes.BIGINT: + case FieldType.BIGINT: schema.bigint(key) break - case FieldTypes.BOOLEAN: + case FieldType.BOOLEAN: schema.boolean(key) break - case FieldTypes.DATETIME: + case FieldType.DATETIME: schema.datetime(key, { useTz: !column.ignoreTimezones, }) break - case FieldTypes.ARRAY: + case FieldType.ARRAY: schema.json(key) break - case FieldTypes.LINK: + case FieldType.LINK: // this side of the relationship doesn't need any SQL work if ( column.relationshipType !== RelationshipType.MANY_TO_ONE && @@ -121,22 +127,18 @@ function generateSchema( } } - if (renamed) { + const oldType = renamed ? oldTable?.schema[renamed.old].type : undefined + if (renamed && oldType && !isIgnoredType(oldType)) { schema.renameColumn(renamed.old, renamed.updated) } // need to check if any columns have been deleted if (oldTable) { - const deletedColumns = Object.entries(oldTable.schema) - .filter( - ([key, schema]) => - schema.type !== FieldTypes.LINK && - schema.type !== FieldTypes.FORMULA && - table.schema[key] == null - ) - .map(([key]) => key) - deletedColumns.forEach(key => { - if (renamed?.old === key) { + const deletedColumns = Object.entries(oldTable.schema).filter( + ([key, column]) => isIgnoredType(column.type) && table.schema[key] == null + ) + deletedColumns.forEach(([key, column]) => { + if (renamed?.old === key || isIgnoredType(column.type)) { return } if (oldTable.constrained && oldTable.constrained.indexOf(key) !== -1) { diff --git a/yarn.lock b/yarn.lock index 6d21d3a3ee..c1ea211391 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1999,13 +1999,20 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": version "7.23.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885" integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg== dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.13.10": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.6.tgz#c05e610dc228855dc92ef1b53d07389ed8ab521d" + integrity sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.22.5", "@babel/template@^7.3.3": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" @@ -5523,16 +5530,16 @@ "@types/passport" "*" "@types/koa-send@*": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@types/koa-send/-/koa-send-4.1.5.tgz#c88362b07f0c12fd94ec9d61590a307be3f81a37" - integrity sha512-O2qnxAKr7MoAxHHUitJejMWw45b9QtgTra0pnVDl/XoNdYTdZOgwj8wSVDon0qXg/lrcYHye4LFbAaSfSWwnrg== + version "4.1.6" + resolved "https://registry.yarnpkg.com/@types/koa-send/-/koa-send-4.1.6.tgz#15d90e95e3ccce669a15b6a3c56c3a650a167cea" + integrity sha512-vgnNGoOJkx7FrF0Jl6rbK1f8bBecqAchKpXtKuXzqIEdXTDO6dsSTjr+eZ5m7ltSjH4K/E7auNJEQCAd0McUPA== dependencies: "@types/koa" "*" "@types/koa-static@^4.0.2": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/koa-static/-/koa-static-4.0.3.tgz#e008a7f6d8a7518c112fa67ba526fd2785d4cc85" - integrity sha512-4U9uZwXqYAudDLDVkw1prJM5avn9/lHLVEwoyyI/ITZluWkBdmirkj8EsOLG6kLr0XFZdViR0ZBtQ3oetSsr3g== + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/koa-static/-/koa-static-4.0.4.tgz#ce6f2a5d14cc7ef19f9bf6ee8e4f3eadfcc77323" + integrity sha512-j1AUzzl7eJYEk9g01hNTlhmipFh8RFbOQmaMNLvLcNNAkPw0bdTs3XTa3V045XFlrWN0QYnblbDJv2RzawTn6A== dependencies: "@types/koa" "*" "@types/koa-send" "*" @@ -5654,7 +5661,7 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=12.12.47", "@types/node@>=13.13.4", "@types/node@>=13.7.0", "@types/node@>=8.1.0": +"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=12.12.47", "@types/node@>=13.13.4", "@types/node@>=13.7.0": version "20.8.9" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.9.tgz#646390b4fab269abce59c308fc286dcd818a2b08" integrity sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg== @@ -5681,10 +5688,17 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.37.tgz#0bfcd173e8e1e328337473a8317e37b3b14fd30d" integrity sha512-7GgtHCs/QZrBrDzgIJnQtuSvhFSwhyYSI2uafSwZoNt1iOGhEN5fwNrQMjtONyHm9+/LoA4453jH0CMYcr06Pg== +"@types/node@>=8.1.0": + version "20.10.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.4.tgz#b246fd84d55d5b1b71bf51f964bd514409347198" + integrity sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg== + dependencies: + undici-types "~5.26.4" + "@types/nodemailer@^6.4.4": - version "6.4.13" - resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.13.tgz#3b3b47a27d1a33631a16763eb2ecdbd567147296" - integrity sha512-889Vq/77eEpidCwh52sVWpbnqQmIwL8yVBekNbrztVEaWKOCRH3Eq6hjIJh1jwsGDEAJEH0RR+YhpH9mfELLKA== + version "6.4.14" + resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.14.tgz#5c81a5e856db7f8ede80013e6dbad7c5fb2283e2" + integrity sha512-fUWthHO9k9DSdPCSPRqcu6TWhYyxTBg382vlNIttSe9M7XfsT06y0f24KHXtbnijPGGRIcVvdKHTNikOI6qiHA== dependencies: "@types/node" "*" @@ -5694,9 +5708,9 @@ integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== "@types/oauth@*": - version "0.9.3" - resolved "https://registry.yarnpkg.com/@types/oauth/-/oauth-0.9.3.tgz#4be90beb6c4a23e1a1614c966a165af1ef5e5e0d" - integrity sha512-avZiwxSz/WS6EaEjhchzXKgWtlGGYGnEVJoHuQuDLHf7gIW1Gmm9eIxOMuJ6umQNNKZkJ3Uy+C/rLzEvL3I8Sw== + version "0.9.4" + resolved "https://registry.yarnpkg.com/@types/oauth/-/oauth-0.9.4.tgz#dcbab5efa2f34f312b915f80685760ccc8111e0a" + integrity sha512-qk9orhti499fq5XxKCCEbd0OzdPZuancneyse3KtR+vgMiHRbh+mn8M4G6t64ob/Fg+GZGpa565MF/2dKWY32A== dependencies: "@types/node" "*" @@ -5709,9 +5723,9 @@ dotenv "^8.2.0" "@types/passport-google-oauth@^1.0.42": - version "1.0.44" - resolved "https://registry.yarnpkg.com/@types/passport-google-oauth/-/passport-google-oauth-1.0.44.tgz#b450dd05c7bcd01a927be79602364c98b0f81da8" - integrity sha512-G4whyY+OKENthpR334PGPMxJc1LfvTJXirbJrk6ujr3LRJ/Bv7HoAxROJdYdVrajKNdc0i4v2msKPds9cBUzfw== + version "1.0.45" + resolved "https://registry.yarnpkg.com/@types/passport-google-oauth/-/passport-google-oauth-1.0.45.tgz#c986c787ec9706b4a596d2bae43342b50b54973d" + integrity sha512-O3Y3DDKnf9lR8+DSaUOCEGF6aFjVYdI8TLhQYtySZ3Sq75c5tGYJ0KJRDZw0GsyLD/Que0nqFkP/GnDVwZZL9w== dependencies: "@types/express" "*" "@types/passport" "*" @@ -5724,18 +5738,18 @@ "@types/passport-oauth2" "*" "@types/passport-oauth2@*": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@types/passport-oauth2/-/passport-oauth2-1.4.14.tgz#6982575b960eb7f001e28103ac3562349f1cded3" - integrity sha512-wZBvnRwqdvm35l1Jn9ebYm2Q7UtxYIdBu1PjoKXMoxJytniVjXxYJmrlDXn5fMZROWbJbnEnp1XSDANqtvMdGQ== + version "1.4.15" + resolved "https://registry.yarnpkg.com/@types/passport-oauth2/-/passport-oauth2-1.4.15.tgz#34f2684f53aad36e664cd01ca9879224229f47e7" + integrity sha512-9cUTP/HStNSZmhxXGuRrBJfEWzIEJRub2eyJu3CvkA+8HAMc9W3aKdFhVq+Qz1hi42qn+GvSAnz3zwacDSYWpw== dependencies: "@types/express" "*" "@types/oauth" "*" "@types/passport" "*" "@types/passport@*": - version "1.0.14" - resolved "https://registry.yarnpkg.com/@types/passport/-/passport-1.0.14.tgz#7ca891b04ae08d7ca4dbf30fece7c86174a16db9" - integrity sha512-D6p2ygR2S7Cq5PO7iUaEIQu/5WrM0tONu6Lxgk0C9r3lafQIlVpWCo3V/KI9To3OqHBxcfQaOeK+8AvwW5RYmw== + version "1.0.16" + resolved "https://registry.yarnpkg.com/@types/passport/-/passport-1.0.16.tgz#5a2918b180a16924c4d75c31254c31cdca5ce6cf" + integrity sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A== dependencies: "@types/express" "*" @@ -5979,9 +5993,9 @@ "@types/node" "*" "@types/server-destroy@^1.0.1": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/server-destroy/-/server-destroy-1.0.2.tgz#d83dce5ea8cf2b88f643d987863b8c619bc644a4" - integrity sha512-Ac4skQzgViPGKqWU89yrtDDfZHvwDxQOzGnd4aS6Tab9IL3VatvfYk2LScKGNS/EML21yvF/9Zy4lMl74tXkPw== + version "1.0.3" + resolved "https://registry.yarnpkg.com/@types/server-destroy/-/server-destroy-1.0.3.tgz#2460932ea3a02a70ec99669c8f40ff089a5b8a2b" + integrity sha512-Qq0fn70C7TLDG1W9FCblKufNWW1OckQ41dVKV2Dku5KdZF7bexezG4e2WBaBKhdwL3HZ+cYCEIKwg2BRgzrWmA== dependencies: "@types/node" "*" @@ -18141,7 +18155,14 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" -posthog-js@^1.13.4, posthog-js@^1.36.0: +posthog-js@^1.13.4: + version "1.94.4" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.94.4.tgz#f480985e0fc131cc81edeb154d694ac5aca2e135" + integrity sha512-1usqOEkGE0ntit99G4TM1iPoq4QBbd5KcuovWroTy0PRJU8cOAfAT3FaJu+lX4B7izWo4DFjvesM/MOaJzLW/Q== + dependencies: + fflate "^0.4.1" + +posthog-js@^1.36.0: version "1.87.2" resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.87.2.tgz#0e9395ea93d50bb624f0be19f254e62e54ae504d" integrity sha512-pdxEylfxwEDwwz7g5dunPucvAN51RAOWWQmkcqHsLNHlV5o5bTaTwcAXaWB1IUn3xKPuKYE2lqbdB3vC4H4rFQ== @@ -23006,19 +23027,6 @@ yargs@^17.3.1, yargs@^17.5.1, yargs@^17.6.2, yargs@^17.7.2: y18n "^5.0.5" yargs-parser "^21.1.1" -yargs@^17.7.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"