From 81cd2a155967b322fa9689a86f93132cdbea090e Mon Sep 17 00:00:00 2001
From: Sam Rose <hello@samwho.dev>
Date: Mon, 8 Apr 2024 14:58:48 +0100
Subject: [PATCH 1/4] Attempt to fix View / ViewV2 types.

---
 .../src/api/controllers/view/viewsV2.ts       |  2 +-
 packages/server/src/sdk/app/tables/getters.ts |  4 ++-
 packages/server/src/sdk/app/views/external.ts | 30 ++++++++++++-------
 packages/server/src/sdk/app/views/index.ts    | 25 +++++++++++-----
 packages/server/src/sdk/app/views/internal.ts | 26 +++++++++-------
 .../server/src/tests/utilities/api/viewV2.ts  | 10 +++----
 packages/types/src/api/web/app/table.ts       |  9 ++----
 packages/types/src/api/web/app/view.ts        | 13 ++++----
 packages/types/src/documents/app/view.ts      |  6 +++-
 9 files changed, 74 insertions(+), 51 deletions(-)

diff --git a/packages/server/src/api/controllers/view/viewsV2.ts b/packages/server/src/api/controllers/view/viewsV2.ts
index a386ac303f..00009ea17e 100644
--- a/packages/server/src/api/controllers/view/viewsV2.ts
+++ b/packages/server/src/api/controllers/view/viewsV2.ts
@@ -41,7 +41,7 @@ async function parseSchema(view: CreateViewRequest) {
 
 export async function get(ctx: Ctx<void, ViewResponse>) {
   ctx.body = {
-    data: await sdk.views.get(ctx.params.viewId, { enriched: true }),
+    data: await sdk.views.get(ctx.params.viewId),
   }
 }
 
diff --git a/packages/server/src/sdk/app/tables/getters.ts b/packages/server/src/sdk/app/tables/getters.ts
index 72a6ab61f1..414af2c837 100644
--- a/packages/server/src/sdk/app/tables/getters.ts
+++ b/packages/server/src/sdk/app/tables/getters.ts
@@ -142,7 +142,9 @@ export function enrichViewSchemas(table: Table): TableResponse {
   return {
     ...table,
     views: Object.values(table.views ?? [])
-      .map(v => sdk.views.enrichSchema(v, table.schema))
+      .map(v =>
+        sdk.views.isV2(v) ? sdk.views.enrichSchema(v, table.schema) : v
+      )
       .reduce((p, v) => {
         p[v.name!] = v
         return p
diff --git a/packages/server/src/sdk/app/views/external.ts b/packages/server/src/sdk/app/views/external.ts
index 47301873f5..0f96bcc061 100644
--- a/packages/server/src/sdk/app/views/external.ts
+++ b/packages/server/src/sdk/app/views/external.ts
@@ -1,4 +1,4 @@
-import { ViewV2 } from "@budibase/types"
+import { ViewV2, ViewV2Enriched } from "@budibase/types"
 import { context, HTTPError } from "@budibase/backend-core"
 
 import sdk from "../../../sdk"
@@ -6,26 +6,34 @@ import * as utils from "../../../db/utils"
 import { enrichSchema, isV2 } from "."
 import { breakExternalTableId } from "../../../integrations/utils"
 
-export async function get(
-  viewId: string,
-  opts?: { enriched: boolean }
-): Promise<ViewV2> {
+export async function get(viewId: string): Promise<ViewV2> {
   const { tableId } = utils.extractViewInfoFromID(viewId)
 
   const { datasourceId, tableName } = breakExternalTableId(tableId)
   const ds = await sdk.datasources.get(datasourceId!)
 
   const table = ds.entities![tableName!]
-  const views = Object.values(table.views!)
-  const found = views.find(v => isV2(v) && v.id === viewId)
+  const views = Object.values(table.views!).filter(isV2)
+  const found = views.find(v => v.id === viewId)
   if (!found) {
     throw new Error("No view found")
   }
-  if (opts?.enriched) {
-    return enrichSchema(found, table.schema) as ViewV2
-  } else {
-    return found as ViewV2
+  return found
+}
+
+export async function getEnriched(viewId: string): Promise<ViewV2Enriched> {
+  const { tableId } = utils.extractViewInfoFromID(viewId)
+
+  const { datasourceId, tableName } = breakExternalTableId(tableId)
+  const ds = await sdk.datasources.get(datasourceId!)
+
+  const table = ds.entities![tableName!]
+  const views = Object.values(table.views!).filter(isV2)
+  const found = views.find(v => v.id === viewId)
+  if (!found) {
+    throw new Error("No view found")
   }
+  return enrichSchema(found, table.schema)
 }
 
 export async function create(
diff --git a/packages/server/src/sdk/app/views/index.ts b/packages/server/src/sdk/app/views/index.ts
index 67e7158f21..9cfd2697f7 100644
--- a/packages/server/src/sdk/app/views/index.ts
+++ b/packages/server/src/sdk/app/views/index.ts
@@ -1,4 +1,10 @@
-import { RenameColumn, TableSchema, View, ViewV2 } from "@budibase/types"
+import {
+  RenameColumn,
+  TableSchema,
+  View,
+  ViewV2,
+  ViewV2Enriched,
+} from "@budibase/types"
 import { db as dbCore } from "@budibase/backend-core"
 import { cloneDeep } from "lodash"
 
@@ -16,12 +22,14 @@ function pickApi(tableId: any) {
   return internal
 }
 
-export async function get(
-  viewId: string,
-  opts?: { enriched: boolean }
-): Promise<ViewV2> {
+export async function get(viewId: string): Promise<ViewV2> {
   const { tableId } = utils.extractViewInfoFromID(viewId)
-  return pickApi(tableId).get(viewId, opts)
+  return pickApi(tableId).get(viewId)
+}
+
+export async function getEnriched(viewId: string): Promise<ViewV2Enriched> {
+  const { tableId } = utils.extractViewInfoFromID(viewId)
+  return pickApi(tableId).getEnriched(viewId)
 }
 
 export async function create(
@@ -52,7 +60,10 @@ export function allowedFields(view: View | ViewV2) {
   ]
 }
 
-export function enrichSchema(view: View | ViewV2, tableSchema: TableSchema) {
+export function enrichSchema(
+  view: ViewV2,
+  tableSchema: TableSchema
+): ViewV2Enriched {
   if (!sdk.views.isV2(view)) {
     return view
   }
diff --git a/packages/server/src/sdk/app/views/internal.ts b/packages/server/src/sdk/app/views/internal.ts
index d1dedd8566..7b2f9f6c80 100644
--- a/packages/server/src/sdk/app/views/internal.ts
+++ b/packages/server/src/sdk/app/views/internal.ts
@@ -1,26 +1,30 @@
-import { ViewV2 } from "@budibase/types"
+import { ViewV2, ViewV2Enriched } from "@budibase/types"
 import { context, HTTPError } from "@budibase/backend-core"
 
 import sdk from "../../../sdk"
 import * as utils from "../../../db/utils"
 import { enrichSchema, isV2 } from "."
 
-export async function get(
-  viewId: string,
-  opts?: { enriched: boolean }
-): Promise<ViewV2> {
+export async function get(viewId: string): Promise<ViewV2> {
   const { tableId } = utils.extractViewInfoFromID(viewId)
   const table = await sdk.tables.getTable(tableId)
-  const views = Object.values(table.views!)
-  const found = views.find(v => isV2(v) && v.id === viewId)
+  const views = Object.values(table.views!).filter(isV2)
+  const found = views.find(v => v.id === viewId)
   if (!found) {
     throw new Error("No view found")
   }
-  if (opts?.enriched) {
-    return enrichSchema(found, table.schema) as ViewV2
-  } else {
-    return found as ViewV2
+  return found
+}
+
+export async function getEnriched(viewId: string): Promise<ViewV2Enriched> {
+  const { tableId } = utils.extractViewInfoFromID(viewId)
+  const table = await sdk.tables.getTable(tableId)
+  const views = Object.values(table.views!).filter(isV2)
+  const found = views.find(v => v.id === viewId)
+  if (!found) {
+    throw new Error("No view found")
   }
+  return enrichSchema(found, table.schema)
 }
 
 export async function create(
diff --git a/packages/server/src/tests/utilities/api/viewV2.ts b/packages/server/src/tests/utilities/api/viewV2.ts
index 2bc2357551..36aa935696 100644
--- a/packages/server/src/tests/utilities/api/viewV2.ts
+++ b/packages/server/src/tests/utilities/api/viewV2.ts
@@ -4,9 +4,9 @@ import {
   ViewV2,
   SearchViewRowRequest,
   PaginatedSearchRowResponse,
+  ViewV2Enriched,
 } from "@budibase/types"
 import { Expectations, TestAPI } from "./base"
-import sdk from "../../../sdk"
 
 export class ViewV2API extends TestAPI {
   create = async (
@@ -44,10 +44,10 @@ export class ViewV2API extends TestAPI {
     return await this._delete(`/api/v2/views/${viewId}`, { expectations: exp })
   }
 
-  get = async (viewId: string) => {
-    return await this.config.doInContext(this.config.appId, () =>
-      sdk.views.get(viewId)
-    )
+  get = async (viewId: string, expectations?: Expectations) => {
+    return await this._get<ViewV2Enriched>(`/api/v2/views/${viewId}`, {
+      expectations,
+    })
   }
 
   search = async (
diff --git a/packages/types/src/api/web/app/table.ts b/packages/types/src/api/web/app/table.ts
index f4d6720516..ffe59ae395 100644
--- a/packages/types/src/api/web/app/table.ts
+++ b/packages/types/src/api/web/app/table.ts
@@ -3,16 +3,11 @@ import {
   Row,
   Table,
   TableRequest,
-  TableSchema,
   View,
-  ViewV2,
+  ViewV2Enriched,
 } from "../../../documents"
 
-interface ViewV2Response extends ViewV2 {
-  schema: TableSchema
-}
-
-export type TableViewsResponse = { [key: string]: View | ViewV2Response }
+export type TableViewsResponse = { [key: string]: View | ViewV2Enriched }
 
 export interface TableResponse extends Table {
   views?: TableViewsResponse
diff --git a/packages/types/src/api/web/app/view.ts b/packages/types/src/api/web/app/view.ts
index 30e7bf77d7..c00bc0e468 100644
--- a/packages/types/src/api/web/app/view.ts
+++ b/packages/types/src/api/web/app/view.ts
@@ -1,14 +1,13 @@
-import { ViewV2, UIFieldMetadata } from "../../../documents"
+import { ViewV2, ViewV2Enriched } from "../../../documents"
 
 export interface ViewResponse {
   data: ViewV2
 }
 
-export interface CreateViewRequest
-  extends Omit<ViewV2, "version" | "id" | "schema"> {
-  schema?: Record<string, UIFieldMetadata>
+export interface ViewResponseEnriched {
+  data: ViewV2Enriched
 }
 
-export interface UpdateViewRequest extends Omit<ViewV2, "schema"> {
-  schema?: Record<string, UIFieldMetadata>
-}
+export interface CreateViewRequest extends Omit<ViewV2, "version" | "id"> {}
+
+export interface UpdateViewRequest extends ViewV2 {}
diff --git a/packages/types/src/documents/app/view.ts b/packages/types/src/documents/app/view.ts
index 7b93d24f3d..8a36b96b4e 100644
--- a/packages/types/src/documents/app/view.ts
+++ b/packages/types/src/documents/app/view.ts
@@ -1,5 +1,5 @@
 import { SearchFilter, SortOrder, SortType } from "../../api"
-import { UIFieldMetadata } from "./table"
+import { TableSchema, UIFieldMetadata } from "./table"
 import { Document } from "../document"
 import { DBView } from "../../sdk"
 
@@ -48,6 +48,10 @@ export interface ViewV2 {
   schema?: Record<string, UIFieldMetadata>
 }
 
+export interface ViewV2Enriched extends ViewV2 {
+  schema?: TableSchema
+}
+
 export type ViewSchema = ViewCountOrSumSchema | ViewStatisticsSchema
 
 export interface ViewCountOrSumSchema {

From d2c0842c4535008f4938ed972587ccc835466bcd Mon Sep 17 00:00:00 2001
From: Sam Rose <hello@samwho.dev>
Date: Mon, 8 Apr 2024 15:17:24 +0100
Subject: [PATCH 2/4] Fix viewV2 tests (for now)

---
 packages/server/src/api/controllers/view/viewsV2.ts |  5 +++--
 packages/server/src/sdk/app/views/index.ts          |  5 -----
 packages/server/src/tests/utilities/api/viewV2.ts   | 10 +++++-----
 3 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/packages/server/src/api/controllers/view/viewsV2.ts b/packages/server/src/api/controllers/view/viewsV2.ts
index 00009ea17e..eb28883e15 100644
--- a/packages/server/src/api/controllers/view/viewsV2.ts
+++ b/packages/server/src/api/controllers/view/viewsV2.ts
@@ -6,6 +6,7 @@ import {
   UIFieldMetadata,
   UpdateViewRequest,
   ViewResponse,
+  ViewResponseEnriched,
   ViewV2,
 } from "@budibase/types"
 import { builderSocket, gridSocket } from "../../../websockets"
@@ -39,9 +40,9 @@ async function parseSchema(view: CreateViewRequest) {
   return finalViewSchema
 }
 
-export async function get(ctx: Ctx<void, ViewResponse>) {
+export async function get(ctx: Ctx<void, ViewResponseEnriched>) {
   ctx.body = {
-    data: await sdk.views.get(ctx.params.viewId),
+    data: await sdk.views.getEnriched(ctx.params.viewId),
   }
 }
 
diff --git a/packages/server/src/sdk/app/views/index.ts b/packages/server/src/sdk/app/views/index.ts
index 9cfd2697f7..2edfd900c4 100644
--- a/packages/server/src/sdk/app/views/index.ts
+++ b/packages/server/src/sdk/app/views/index.ts
@@ -8,7 +8,6 @@ import {
 import { db as dbCore } from "@budibase/backend-core"
 import { cloneDeep } from "lodash"
 
-import sdk from "../../../sdk"
 import * as utils from "../../../db/utils"
 import { isExternalTableID } from "../../../integrations/utils"
 
@@ -64,10 +63,6 @@ export function enrichSchema(
   view: ViewV2,
   tableSchema: TableSchema
 ): ViewV2Enriched {
-  if (!sdk.views.isV2(view)) {
-    return view
-  }
-
   let schema = cloneDeep(tableSchema)
   const anyViewOrder = Object.values(view.schema || {}).some(
     ui => ui.order != null
diff --git a/packages/server/src/tests/utilities/api/viewV2.ts b/packages/server/src/tests/utilities/api/viewV2.ts
index 36aa935696..53b67a23f8 100644
--- a/packages/server/src/tests/utilities/api/viewV2.ts
+++ b/packages/server/src/tests/utilities/api/viewV2.ts
@@ -4,9 +4,9 @@ import {
   ViewV2,
   SearchViewRowRequest,
   PaginatedSearchRowResponse,
-  ViewV2Enriched,
 } from "@budibase/types"
 import { Expectations, TestAPI } from "./base"
+import sdk from "../../../sdk"
 
 export class ViewV2API extends TestAPI {
   create = async (
@@ -44,10 +44,10 @@ export class ViewV2API extends TestAPI {
     return await this._delete(`/api/v2/views/${viewId}`, { expectations: exp })
   }
 
-  get = async (viewId: string, expectations?: Expectations) => {
-    return await this._get<ViewV2Enriched>(`/api/v2/views/${viewId}`, {
-      expectations,
-    })
+  get = async (viewId: string) => {
+    return await this.config.doInContext(this.config.getAppId(), () =>
+      sdk.views.get(viewId)
+    )
   }
 
   search = async (

From 8ad0729317b96222b341560066d7d985b57ee720 Mon Sep 17 00:00:00 2001
From: Sam Rose <hello@samwho.dev>
Date: Mon, 8 Apr 2024 15:48:27 +0100
Subject: [PATCH 3/4] Fix ViewV2API.get to hit the API instead of using the
 sdk.

---
 .../server/src/api/routes/tests/viewV2.spec.ts     | 14 +++++++-------
 packages/server/src/tests/utilities/api/viewV2.ts  |  6 +++---
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/packages/server/src/api/routes/tests/viewV2.spec.ts b/packages/server/src/api/routes/tests/viewV2.spec.ts
index 1ed6b45a08..a4ecd7c818 100644
--- a/packages/server/src/api/routes/tests/viewV2.spec.ts
+++ b/packages/server/src/api/routes/tests/viewV2.spec.ts
@@ -181,7 +181,7 @@ describe.each([
 
       const createdView = await config.api.viewV2.create(newView)
 
-      expect(await config.api.viewV2.get(createdView.id)).toEqual({
+      expect(createdView).toEqual({
         ...newView,
         schema: {
           Price: {
@@ -398,7 +398,7 @@ describe.each([
     })
 
     it("updates only UI schema overrides", async () => {
-      await config.api.viewV2.update({
+      const updatedView = await config.api.viewV2.update({
         ...view,
         schema: {
           Price: {
@@ -417,7 +417,7 @@ describe.each([
         } as Record<string, FieldSchema>,
       })
 
-      expect(await config.api.viewV2.get(view.id)).toEqual({
+      expect(updatedView).toEqual({
         ...view,
         schema: {
           Price: {
@@ -479,17 +479,17 @@ describe.each([
 
   describe("fetch view (through table)", () => {
     it("should be able to fetch a view V2", async () => {
-      const newView: CreateViewRequest = {
+      const res = await config.api.viewV2.create({
         name: generator.name(),
         tableId: table._id!,
         schema: {
           Price: { visible: false },
           Category: { visible: true },
         },
-      }
-      const res = await config.api.viewV2.create(newView)
+      })
+      expect(res.schema?.Price).toBeUndefined()
+
       const view = await config.api.viewV2.get(res.id)
-      expect(view!.schema?.Price).toBeUndefined()
       const updatedTable = await config.api.table.get(table._id!)
       const viewSchema = updatedTable.views![view!.name!].schema as Record<
         string,
diff --git a/packages/server/src/tests/utilities/api/viewV2.ts b/packages/server/src/tests/utilities/api/viewV2.ts
index 53b67a23f8..653294188d 100644
--- a/packages/server/src/tests/utilities/api/viewV2.ts
+++ b/packages/server/src/tests/utilities/api/viewV2.ts
@@ -4,6 +4,7 @@ import {
   ViewV2,
   SearchViewRowRequest,
   PaginatedSearchRowResponse,
+  ViewResponseEnriched,
 } from "@budibase/types"
 import { Expectations, TestAPI } from "./base"
 import sdk from "../../../sdk"
@@ -45,9 +46,8 @@ export class ViewV2API extends TestAPI {
   }
 
   get = async (viewId: string) => {
-    return await this.config.doInContext(this.config.getAppId(), () =>
-      sdk.views.get(viewId)
-    )
+    return (await this._get<ViewResponseEnriched>(`/api/v2/views/${viewId}`))
+      .data
   }
 
   search = async (

From ee45efd6585fac8f058a0cba80e699dfef407e01 Mon Sep 17 00:00:00 2001
From: Sam Rose <hello@samwho.dev>
Date: Mon, 8 Apr 2024 15:48:59 +0100
Subject: [PATCH 4/4] Remove unused import.

---
 packages/server/src/tests/utilities/api/viewV2.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/packages/server/src/tests/utilities/api/viewV2.ts b/packages/server/src/tests/utilities/api/viewV2.ts
index 653294188d..9741240f27 100644
--- a/packages/server/src/tests/utilities/api/viewV2.ts
+++ b/packages/server/src/tests/utilities/api/viewV2.ts
@@ -7,7 +7,6 @@ import {
   ViewResponseEnriched,
 } from "@budibase/types"
 import { Expectations, TestAPI } from "./base"
-import sdk from "../../../sdk"
 
 export class ViewV2API extends TestAPI {
   create = async (