From 7bd84bd0484311d5b8f2eff963e3b625d846d3cb Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Tue, 26 Sep 2023 17:01:30 +0100
Subject: [PATCH] Some typing fixes as well as a fix for the frontend issue of
 tables not correctly having their schemas updated in the table store when
 relationships added.

---
 packages/builder/src/stores/backend/tables.js | 28 ++++++++++++++++++-
 packages/frontend-core/src/api/tables.js      | 12 +++++++-
 .../server/src/api/controllers/table/index.ts | 14 ++++++----
 packages/server/src/integrations/utils.ts     |  6 ++--
 4 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/packages/builder/src/stores/backend/tables.js b/packages/builder/src/stores/backend/tables.js
index 201a67824d..dae8674146 100644
--- a/packages/builder/src/stores/backend/tables.js
+++ b/packages/builder/src/stores/backend/tables.js
@@ -1,7 +1,7 @@
 import { get, writable, derived } from "svelte/store"
 import { cloneDeep } from "lodash/fp"
 import { API } from "api"
-import { SWITCHABLE_TYPES } from "constants/backend"
+import { SWITCHABLE_TYPES, FIELDS } from "constants/backend"
 
 export function createTablesStore() {
   const store = writable({
@@ -21,6 +21,23 @@ export function createTablesStore() {
     }))
   }
 
+  const singleFetch = async tableId => {
+    const table = await API.getTable(tableId)
+    store.update(state => {
+      const list = []
+      // update the list, keep order accurate
+      for (let tbl of state.list) {
+        if (table._id === tbl._id) {
+          list.push(table)
+        } else {
+          list.push(tbl)
+        }
+      }
+      state.list = list
+      return state
+    })
+  }
+
   const select = tableId => {
     store.update(state => ({
       ...state,
@@ -63,6 +80,14 @@ export function createTablesStore() {
     const savedTable = await API.saveTable(updatedTable)
     replaceTable(savedTable._id, savedTable)
     select(savedTable._id)
+    // make sure tables up to date (related)
+    const tableUpdates = []
+    for (let column of Object.values(updatedTable?.schema || {})) {
+      if (column.type === FIELDS.LINK.type) {
+        tableUpdates.push(singleFetch(column.tableId))
+      }
+    }
+    await Promise.all(tableUpdates)
     return savedTable
   }
 
@@ -84,6 +109,7 @@ export function createTablesStore() {
     indexes,
   }) => {
     let draft = cloneDeep(get(derivedStore).selected)
+    console.log(draft)
 
     // delete the original if renaming
     // need to handle if the column had no name, empty string
diff --git a/packages/frontend-core/src/api/tables.js b/packages/frontend-core/src/api/tables.js
index b84bd3076a..a08e35d3d8 100644
--- a/packages/frontend-core/src/api/tables.js
+++ b/packages/frontend-core/src/api/tables.js
@@ -82,8 +82,9 @@ export const buildTableEndpoints = API => ({
       },
     })
   },
+
   /**
-   * Gets a list o tables.
+   * Gets a list of tables.
    */
   getTables: async () => {
     return await API.get({
@@ -91,6 +92,15 @@ export const buildTableEndpoints = API => ({
     })
   },
 
+  /**
+   * Get a single table based on table ID.
+   */
+  getTable: async tableId => {
+    return await API.get({
+      url: `/api/tables/${tableId}`,
+    })
+  },
+
   /**
    * Saves a table.
    * @param table the table to save
diff --git a/packages/server/src/api/controllers/table/index.ts b/packages/server/src/api/controllers/table/index.ts
index 29c41ad985..5029856cf4 100644
--- a/packages/server/src/api/controllers/table/index.ts
+++ b/packages/server/src/api/controllers/table/index.ts
@@ -14,10 +14,12 @@ import {
   Table,
   TableResponse,
   UserCtx,
+  Datasource,
 } from "@budibase/types"
 import sdk from "../../../sdk"
 import { jsonFromCsvString } from "../../../utilities/csv"
 import { builderSocket } from "../../../websockets"
+import { cloneDeep } from "lodash"
 
 function pickApi({ tableId, table }: { tableId?: string; table?: Table }) {
   if (table && !tableId) {
@@ -35,16 +37,16 @@ function pickApi({ tableId, table }: { tableId?: string; table?: Table }) {
 export async function fetch(ctx: UserCtx<void, FetchTablesResponse>) {
   const internal = await sdk.tables.getAllInternalTables()
 
-  const externalTables = await sdk.datasources.getExternalDatasources()
+  const datasources = await sdk.datasources.getExternalDatasources()
 
-  const external = externalTables.flatMap(table => {
-    let entities = table.entities
+  const external = datasources.flatMap(datasource => {
+    let entities = datasource.entities
     if (entities) {
       return Object.values(entities).map<Table>((entity: Table) => ({
         ...entity,
         type: "external",
-        sourceId: table._id,
-        sql: isSQL(table),
+        sourceId: datasource._id,
+        sql: isSQL(datasource),
       }))
     } else {
       return []
@@ -80,7 +82,7 @@ export async function save(ctx: UserCtx<SaveTableRequest, SaveTableResponse>) {
   ctx.eventEmitter &&
     ctx.eventEmitter.emitTable(`table:save`, appId, { ...savedTable })
   ctx.body = savedTable
-  builderSocket?.emitTableUpdate(ctx, { ...savedTable })
+  builderSocket?.emitTableUpdate(ctx, cloneDeep(savedTable))
 }
 
 export async function destroy(ctx: UserCtx) {
diff --git a/packages/server/src/integrations/utils.ts b/packages/server/src/integrations/utils.ts
index 75f4bcbfa1..b6b6f60fee 100644
--- a/packages/server/src/integrations/utils.ts
+++ b/packages/server/src/integrations/utils.ts
@@ -1,4 +1,4 @@
-import { SqlQuery, Table, SearchFilters } from "@budibase/types"
+import { SqlQuery, Table, SearchFilters, Datasource } from "@budibase/types"
 import { DocumentType, SEPARATOR } from "../db/utils"
 import {
   FieldTypes,
@@ -184,7 +184,9 @@ export function getSqlQuery(query: SqlQuery | string): SqlQuery {
   }
 }
 
-export const isSQL = helpers.isSQL
+export function isSQL(datasource: Datasource) {
+  return helpers.isSQL(datasource)
+}
 
 export function isIsoDateString(str: string) {
   const trimmedValue = str.trim()