@budibase/server 3.4.15 → 3.4.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,511 +1,532 @@
1
1
  import {
2
2
  AIOperationEnum,
3
3
  CalculationType,
4
+ Datasource,
4
5
  FieldType,
5
6
  RelationshipType,
6
- SourceName,
7
7
  Table,
8
8
  ViewV2,
9
9
  ViewV2Type,
10
10
  } from "@budibase/types"
11
11
  import { buildSqlFieldList } from "../sqlUtils"
12
12
  import { structures } from "../../../../routes/tests/utilities"
13
- import { sql } from "@budibase/backend-core"
14
13
  import { generator } from "@budibase/backend-core/tests"
15
14
  import { generateViewID } from "../../../../../db/utils"
16
15
 
17
- import sdk from "../../../../../sdk"
18
- import { cloneDeep } from "lodash"
19
16
  import { utils } from "@budibase/shared-core"
17
+ import {
18
+ DatabaseName,
19
+ datasourceDescribe,
20
+ } from "../../../../../integrations/tests/utils"
21
+ import { context } from "@budibase/backend-core"
20
22
 
21
- jest.mock("../../../../../sdk/app/views", () => ({
22
- ...jest.requireActual("../../../../../sdk/app/views"),
23
- getTable: jest.fn(),
24
- }))
25
- const getTableMock = sdk.views.getTable as jest.MockedFunction<
26
- typeof sdk.views.getTable
27
- >
28
-
29
- describe("buildSqlFieldList", () => {
30
- let allTables: Record<string, Table>
31
-
32
- class TableConfig {
33
- private _table: Table & { _id: string }
34
-
35
- constructor(name: string) {
36
- this._table = {
37
- ...structures.tableForDatasource({
38
- type: "datasource",
39
- source: SourceName.POSTGRES,
40
- }),
41
- name,
42
- _id: sql.utils.buildExternalTableId("ds_id", name),
43
- schema: {
44
- name: {
45
- name: "name",
46
- type: FieldType.STRING,
47
- },
48
- description: {
49
- name: "description",
50
- type: FieldType.STRING,
51
- },
52
- amount: {
53
- name: "amount",
54
- type: FieldType.NUMBER,
55
- },
56
- },
57
- }
23
+ const descriptions = datasourceDescribe({
24
+ only: [DatabaseName.POSTGRES],
25
+ })
58
26
 
59
- allTables[name] = this._table
60
- }
27
+ if (descriptions.length) {
28
+ describe.each(descriptions)(
29
+ "buildSqlFieldList ($dbName)",
30
+ ({ config, dsProvider }) => {
31
+ let allTables: Record<string, Table>
32
+ let datasource: Datasource
33
+
34
+ beforeEach(async () => {
35
+ const ds = await dsProvider()
36
+ datasource = ds.datasource!
37
+ allTables = {}
38
+ })
61
39
 
62
- withHiddenField(field: string) {
63
- this._table.schema[field].visible = false
64
- return this
65
- }
40
+ class TableConfig {
41
+ private _table: Table
66
42
 
67
- withField(
68
- name: string,
69
- type:
70
- | FieldType.STRING
71
- | FieldType.NUMBER
72
- | FieldType.FORMULA
73
- | FieldType.AI,
74
- options?: { visible: boolean }
75
- ) {
76
- switch (type) {
77
- case FieldType.NUMBER:
78
- case FieldType.STRING:
79
- this._table.schema[name] = {
43
+ constructor(name: string) {
44
+ this._table = {
45
+ ...structures.tableForDatasource(datasource),
80
46
  name,
81
- type,
82
- ...options,
47
+ schema: {
48
+ name: {
49
+ name: "name",
50
+ type: FieldType.STRING,
51
+ },
52
+ description: {
53
+ name: "description",
54
+ type: FieldType.STRING,
55
+ },
56
+ amount: {
57
+ name: "amount",
58
+ type: FieldType.NUMBER,
59
+ },
60
+ },
83
61
  }
84
- break
85
- case FieldType.FORMULA:
86
- this._table.schema[name] = {
87
- name,
88
- type,
89
- formula: "any",
90
- ...options,
62
+ }
63
+
64
+ withHiddenField(field: string) {
65
+ this._table.schema[field].visible = false
66
+ return this
67
+ }
68
+
69
+ withField(
70
+ name: string,
71
+ type:
72
+ | FieldType.STRING
73
+ | FieldType.NUMBER
74
+ | FieldType.FORMULA
75
+ | FieldType.AI,
76
+ options?: { visible: boolean }
77
+ ) {
78
+ switch (type) {
79
+ case FieldType.NUMBER:
80
+ case FieldType.STRING:
81
+ this._table.schema[name] = {
82
+ name,
83
+ type,
84
+ ...options,
85
+ }
86
+ break
87
+ case FieldType.FORMULA:
88
+ this._table.schema[name] = {
89
+ name,
90
+ type,
91
+ formula: "any",
92
+ ...options,
93
+ }
94
+ break
95
+ case FieldType.AI:
96
+ this._table.schema[name] = {
97
+ name,
98
+ type,
99
+ operation: AIOperationEnum.PROMPT,
100
+ ...options,
101
+ }
102
+ break
103
+ default:
104
+ utils.unreachable(type)
91
105
  }
92
- break
93
- case FieldType.AI:
106
+ return this
107
+ }
108
+
109
+ withRelation(name: string, toTableId: string) {
94
110
  this._table.schema[name] = {
95
111
  name,
96
- type,
97
- operation: AIOperationEnum.PROMPT,
98
- ...options,
112
+ type: FieldType.LINK,
113
+ relationshipType: RelationshipType.ONE_TO_MANY,
114
+ fieldName: "link",
115
+ foreignKey: "link",
116
+ tableId: toTableId,
99
117
  }
100
- break
101
- default:
102
- utils.unreachable(type)
118
+ return this
119
+ }
120
+
121
+ withPrimary(field: string) {
122
+ this._table.primary = [field]
123
+ return this
124
+ }
125
+
126
+ withDisplay(field: string) {
127
+ this._table.primaryDisplay = field
128
+ return this
129
+ }
130
+
131
+ async create() {
132
+ const table = await config.api.table.save(this._table)
133
+ allTables[table.name] = table
134
+ return table
135
+ }
103
136
  }
104
- return this
105
- }
106
137
 
107
- withRelation(name: string, toTableId: string) {
108
- this._table.schema[name] = {
109
- name,
110
- type: FieldType.LINK,
111
- relationshipType: RelationshipType.ONE_TO_MANY,
112
- fieldName: "link",
113
- tableId: toTableId,
114
- }
115
- return this
116
- }
138
+ class ViewConfig {
139
+ private _view: ViewV2
117
140
 
118
- withPrimary(field: string) {
119
- this._table.primary = [field]
120
- return this
121
- }
141
+ constructor(table: Table) {
142
+ this._view = {
143
+ version: 2,
144
+ id: generateViewID(table._id!),
145
+ name: generator.word(),
146
+ tableId: table._id!,
147
+ }
148
+ }
149
+
150
+ withVisible(field: string) {
151
+ this._view.schema ??= {}
152
+ this._view.schema[field] ??= {}
153
+ this._view.schema[field].visible = true
154
+ return this
155
+ }
156
+
157
+ withHidden(field: string) {
158
+ this._view.schema ??= {}
159
+ this._view.schema[field] ??= {}
160
+ this._view.schema[field].visible = false
161
+ return this
162
+ }
163
+
164
+ withRelationshipColumns(
165
+ field: string,
166
+ columns: Record<string, { visible: boolean }>
167
+ ) {
168
+ this._view.schema ??= {}
169
+ this._view.schema[field] ??= {}
170
+ this._view.schema[field].columns = columns
171
+ return this
172
+ }
173
+
174
+ withCalculation(
175
+ name: string,
176
+ field: string,
177
+ calculationType: CalculationType
178
+ ) {
179
+ this._view.type = ViewV2Type.CALCULATION
180
+ this._view.schema ??= {}
181
+ this._view.schema[name] = {
182
+ field,
183
+ calculationType,
184
+ visible: true,
185
+ }
186
+ return this
187
+ }
122
188
 
123
- withDisplay(field: string) {
124
- this._table.primaryDisplay = field
125
- return this
126
- }
189
+ async create() {
190
+ return await config.api.viewV2.create(this._view)
191
+ }
192
+ }
127
193
 
128
- create() {
129
- return cloneDeep(this._table)
130
- }
131
- }
132
-
133
- class ViewConfig {
134
- private _table: Table
135
- private _view: ViewV2
136
-
137
- constructor(table: Table) {
138
- this._table = table
139
- this._view = {
140
- version: 2,
141
- id: generateViewID(table._id!),
142
- name: generator.word(),
143
- tableId: table._id!,
194
+ const buildSqlFieldListInApp: typeof buildSqlFieldList = async (
195
+ table,
196
+ allTables,
197
+ opts
198
+ ) => {
199
+ return context.doInAppContext(config.getAppId(), () =>
200
+ buildSqlFieldList(table, allTables, opts)
201
+ )
144
202
  }
145
- }
146
203
 
147
- withVisible(field: string) {
148
- this._view.schema ??= {}
149
- this._view.schema[field] ??= {}
150
- this._view.schema[field].visible = true
151
- return this
152
- }
204
+ describe("table", () => {
205
+ it("extracts fields from table schema", async () => {
206
+ const table = await new TableConfig("table").create()
207
+ const result = await buildSqlFieldListInApp(table, {})
208
+ expect(result).toEqual([
209
+ "table.name",
210
+ "table.description",
211
+ "table.amount",
212
+ "table.id",
213
+ ])
214
+ })
153
215
 
154
- withHidden(field: string) {
155
- this._view.schema ??= {}
156
- this._view.schema[field] ??= {}
157
- this._view.schema[field].visible = false
158
- return this
159
- }
216
+ it("excludes hidden fields", async () => {
217
+ const table = await new TableConfig("table")
218
+ .withHiddenField("description")
219
+ .create()
220
+ const result = await buildSqlFieldListInApp(table, {})
221
+ expect(result).toEqual(["table.name", "table.amount", "table.id"])
222
+ })
160
223
 
161
- withRelationshipColumns(
162
- field: string,
163
- columns: Record<string, { visible: boolean }>
164
- ) {
165
- this._view.schema ??= {}
166
- this._view.schema[field] ??= {}
167
- this._view.schema[field].columns = columns
168
- return this
169
- }
224
+ it("excludes non-sql fields fields", async () => {
225
+ const table = await new TableConfig("table")
226
+ .withField("formula", FieldType.FORMULA)
227
+ .withField("ai", FieldType.AI)
228
+ .create()
229
+
230
+ const result = await buildSqlFieldListInApp(table, {})
231
+ expect(result).toEqual([
232
+ "table.name",
233
+ "table.description",
234
+ "table.amount",
235
+ "table.id",
236
+ ])
237
+ })
170
238
 
171
- withCalculation(
172
- name: string,
173
- field: string,
174
- calculationType: CalculationType
175
- ) {
176
- this._view.type = ViewV2Type.CALCULATION
177
- this._view.schema ??= {}
178
- this._view.schema[name] = {
179
- field,
180
- calculationType,
181
- visible: true,
182
- }
183
- return this
184
- }
239
+ it("includes hidden fields if there is a formula column", async () => {
240
+ const table = await new TableConfig("table")
241
+ .withHiddenField("description")
242
+ .withField("formula", FieldType.FORMULA)
243
+ .create()
244
+
245
+ const result = await buildSqlFieldListInApp(table, {})
246
+ expect(result).toEqual([
247
+ "table.name",
248
+ "table.description",
249
+ "table.amount",
250
+ "table.id",
251
+ ])
252
+ })
185
253
 
186
- create() {
187
- getTableMock.mockResolvedValueOnce(this._table)
188
- return cloneDeep(this._view)
189
- }
190
- }
191
-
192
- beforeEach(() => {
193
- jest.clearAllMocks()
194
- allTables = {}
195
- })
196
-
197
- describe("table", () => {
198
- it("extracts fields from table schema", async () => {
199
- const table = new TableConfig("table").create()
200
- const result = await buildSqlFieldList(table, {})
201
- expect(result).toEqual([
202
- "table.name",
203
- "table.description",
204
- "table.amount",
205
- ])
206
- })
207
-
208
- it("excludes hidden fields", async () => {
209
- const table = new TableConfig("table")
210
- .withHiddenField("description")
211
- .create()
212
- const result = await buildSqlFieldList(table, {})
213
- expect(result).toEqual(["table.name", "table.amount"])
214
- })
215
-
216
- it("excludes non-sql fields fields", async () => {
217
- const table = new TableConfig("table")
218
- .withField("formula", FieldType.FORMULA)
219
- .withField("ai", FieldType.AI)
220
- .withRelation("link", "otherTableId")
221
- .create()
222
-
223
- const result = await buildSqlFieldList(table, {})
224
- expect(result).toEqual([
225
- "table.name",
226
- "table.description",
227
- "table.amount",
228
- ])
229
- })
230
-
231
- it("includes hidden fields if there is a formula column", async () => {
232
- const table = new TableConfig("table")
233
- .withHiddenField("description")
234
- .withField("formula", FieldType.FORMULA)
235
- .create()
236
-
237
- const result = await buildSqlFieldList(table, {})
238
- expect(result).toEqual([
239
- "table.name",
240
- "table.description",
241
- "table.amount",
242
- ])
243
- })
244
-
245
- it("includes relationships fields when flagged", async () => {
246
- const otherTable = new TableConfig("linkedTable")
247
- .withField("id", FieldType.NUMBER)
248
- .withPrimary("id")
249
- .withDisplay("name")
250
- .create()
251
-
252
- const table = new TableConfig("table")
253
- .withRelation("link", otherTable._id)
254
- .create()
255
-
256
- const result = await buildSqlFieldList(table, allTables, {
257
- relationships: true,
258
- })
259
- expect(result).toEqual([
260
- "table.name",
261
- "table.description",
262
- "table.amount",
263
- "linkedTable.id",
264
- "linkedTable.name",
265
- ])
266
- })
267
-
268
- it("includes all relationship fields if there is a formula column", async () => {
269
- const otherTable = new TableConfig("linkedTable")
270
- .withField("hidden", FieldType.STRING, { visible: false })
271
- .create()
272
-
273
- const table = new TableConfig("table")
274
- .withRelation("link", otherTable._id)
275
- .withField("formula", FieldType.FORMULA)
276
- .create()
277
-
278
- const result = await buildSqlFieldList(table, allTables, {
279
- relationships: true,
280
- })
281
- expect(result).toEqual([
282
- "table.name",
283
- "table.description",
284
- "table.amount",
285
- "linkedTable.name",
286
- "linkedTable.description",
287
- "linkedTable.amount",
288
- "linkedTable.hidden",
289
- ])
290
- })
291
-
292
- it("never includes non-sql columns from relationships", async () => {
293
- const otherTable = new TableConfig("linkedTable")
294
- .withField("id", FieldType.NUMBER)
295
- .withField("hidden", FieldType.STRING, { visible: false })
296
- .withField("formula", FieldType.FORMULA)
297
- .withField("ai", FieldType.AI)
298
- .withRelation("link", "otherTableId")
299
- .create()
300
-
301
- const table = new TableConfig("table")
302
- .withRelation("link", otherTable._id)
303
- .withField("formula", FieldType.FORMULA)
304
- .create()
305
-
306
- const result = await buildSqlFieldList(table, allTables, {
307
- relationships: true,
308
- })
309
- expect(result).toEqual([
310
- "table.name",
311
- "table.description",
312
- "table.amount",
313
- "linkedTable.name",
314
- "linkedTable.description",
315
- "linkedTable.amount",
316
- "linkedTable.id",
317
- "linkedTable.hidden",
318
- ])
319
- })
320
- })
321
-
322
- describe("view", () => {
323
- it("extracts fields from table schema", async () => {
324
- const view = new ViewConfig(new TableConfig("table").create())
325
- .withVisible("amount")
326
- .withHidden("name")
327
- .create()
328
-
329
- const result = await buildSqlFieldList(view, {})
330
- expect(result).toEqual(["table.amount"])
331
- })
332
-
333
- it("includes all fields if there is a formula column", async () => {
334
- const table = new TableConfig("table")
335
- .withField("formula", FieldType.FORMULA)
336
- .create()
337
- const view = new ViewConfig(table)
338
- .withHidden("name")
339
- .withVisible("amount")
340
- .withVisible("formula")
341
- .create()
342
-
343
- const result = await buildSqlFieldList(view, {})
344
- expect(result).toEqual([
345
- "table.name",
346
- "table.description",
347
- "table.amount",
348
- ])
349
- })
350
-
351
- it("does not includes all fields if the formula column is not included", async () => {
352
- const table = new TableConfig("table")
353
- .withField("formula", FieldType.FORMULA)
354
- .create()
355
- const view = new ViewConfig(table)
356
- .withHidden("name")
357
- .withVisible("amount")
358
- .withHidden("formula")
359
- .create()
360
-
361
- const result = await buildSqlFieldList(view, {})
362
- expect(result).toEqual(["table.amount"])
363
- })
364
-
365
- it("includes relationships columns", async () => {
366
- const otherTable = new TableConfig("linkedTable")
367
- .withField("id", FieldType.NUMBER)
368
- .withField("formula", FieldType.FORMULA)
369
- .withPrimary("id")
370
- .create()
371
-
372
- const table = new TableConfig("table")
373
- .withRelation("link", otherTable._id)
374
- .create()
375
-
376
- const view = new ViewConfig(table)
377
- .withVisible("name")
378
- .withVisible("link")
379
- .withRelationshipColumns("link", {
380
- name: { visible: false },
381
- amount: { visible: true },
382
- formula: { visible: false },
254
+ it("includes relationships fields when flagged", async () => {
255
+ const otherTable = await new TableConfig("linkedTable")
256
+ .withField("id", FieldType.NUMBER)
257
+ .withPrimary("id")
258
+ .withDisplay("name")
259
+ .create()
260
+
261
+ const table = await new TableConfig("table")
262
+ .withRelation("link", otherTable._id!)
263
+ .create()
264
+
265
+ const result = await buildSqlFieldListInApp(table, allTables, {
266
+ relationships: true,
267
+ })
268
+ expect(result).toEqual([
269
+ "table.name",
270
+ "table.description",
271
+ "table.amount",
272
+ "table.id",
273
+ "linkedTable.id",
274
+ "linkedTable.name",
275
+ ])
383
276
  })
384
- .create()
385
277
 
386
- const result = await buildSqlFieldList(view, allTables, {
387
- relationships: true,
388
- })
389
- expect(result).toEqual([
390
- "table.name",
391
- "linkedTable.id",
392
- "linkedTable.amount",
393
- ])
394
- })
395
-
396
- it("excludes relationships fields when view is not included in the view", async () => {
397
- const otherTable = new TableConfig("linkedTable")
398
- .withField("id", FieldType.NUMBER)
399
- .withPrimary("id")
400
- .withDisplay("name")
401
- .create()
402
-
403
- const table = new TableConfig("table")
404
- .withRelation("link", otherTable._id)
405
- .withField("formula", FieldType.FORMULA)
406
- .create()
407
-
408
- const view = new ViewConfig(table)
409
- .withVisible("name")
410
- .withHidden("amount")
411
- .create()
412
-
413
- const result = await buildSqlFieldList(view, allTables, {
414
- relationships: true,
278
+ it("includes all relationship fields if there is a formula column", async () => {
279
+ const otherTable = await new TableConfig("linkedTable")
280
+ .withField("hidden", FieldType.STRING, { visible: false })
281
+ .create()
282
+
283
+ const table = await new TableConfig("table")
284
+ .withRelation("link", otherTable._id!)
285
+ .withField("formula", FieldType.FORMULA)
286
+ .create()
287
+
288
+ const result = await buildSqlFieldListInApp(table, allTables, {
289
+ relationships: true,
290
+ })
291
+ expect(result).toEqual([
292
+ "table.name",
293
+ "table.description",
294
+ "table.amount",
295
+ "table.id",
296
+ "linkedTable.name",
297
+ "linkedTable.description",
298
+ "linkedTable.amount",
299
+ "linkedTable.hidden",
300
+ "linkedTable.id",
301
+ ])
302
+ })
303
+
304
+ it("never includes non-sql columns from relationships", async () => {
305
+ const otherTable = await new TableConfig("linkedTable")
306
+ .withField("hidden", FieldType.STRING, { visible: false })
307
+ .withField("formula", FieldType.FORMULA)
308
+ .withField("ai", FieldType.AI)
309
+ .create()
310
+
311
+ const table = await new TableConfig("table")
312
+ .withRelation("link", otherTable._id!)
313
+ .withField("formula", FieldType.FORMULA)
314
+ .create()
315
+
316
+ const result = await buildSqlFieldListInApp(table, allTables, {
317
+ relationships: true,
318
+ })
319
+ expect(result).toEqual([
320
+ "table.name",
321
+ "table.description",
322
+ "table.amount",
323
+ "table.id",
324
+ "linkedTable.name",
325
+ "linkedTable.description",
326
+ "linkedTable.amount",
327
+ "linkedTable.hidden",
328
+ "linkedTable.id",
329
+ ])
330
+ })
415
331
  })
416
- expect(result).toEqual(["table.name"])
417
- })
418
-
419
- it("does not include relationships columns for hidden links", async () => {
420
- const otherTable = new TableConfig("linkedTable")
421
- .withField("id", FieldType.NUMBER)
422
- .withField("formula", FieldType.FORMULA)
423
- .withPrimary("id")
424
- .create()
425
-
426
- const table = new TableConfig("table")
427
- .withRelation("link", otherTable._id)
428
- .create()
429
-
430
- const view = new ViewConfig(table)
431
- .withVisible("name")
432
- .withHidden("link")
433
- .withRelationshipColumns("link", {
434
- name: { visible: false },
435
- amount: { visible: true },
436
- formula: { visible: false },
332
+
333
+ describe("view", () => {
334
+ it("extracts fields from table schema", async () => {
335
+ const view = await new ViewConfig(
336
+ await new TableConfig("table").create()
337
+ )
338
+ .withVisible("amount")
339
+ .withHidden("name")
340
+ .create()
341
+
342
+ const result = await buildSqlFieldListInApp(view, {})
343
+ expect(result).toEqual(["table.amount", "table.id"])
344
+ })
345
+
346
+ it("includes all fields if there is a formula column", async () => {
347
+ const table = await new TableConfig("table")
348
+ .withField("formula", FieldType.FORMULA)
349
+ .create()
350
+ const view = await new ViewConfig(table)
351
+ .withHidden("name")
352
+ .withVisible("amount")
353
+ .withVisible("formula")
354
+ .create()
355
+
356
+ const result = await buildSqlFieldListInApp(view, {})
357
+ expect(result).toEqual([
358
+ "table.name",
359
+ "table.description",
360
+ "table.amount",
361
+ "table.id",
362
+ ])
363
+ })
364
+
365
+ it("does not includes all fields if the formula column is not included", async () => {
366
+ const table = await new TableConfig("table")
367
+ .withField("formula", FieldType.FORMULA)
368
+ .create()
369
+ const view = await new ViewConfig(table)
370
+ .withHidden("name")
371
+ .withVisible("amount")
372
+ .withHidden("formula")
373
+ .create()
374
+
375
+ const result = await buildSqlFieldListInApp(view, {})
376
+ expect(result).toEqual(["table.amount", "table.id"])
377
+ })
378
+
379
+ it("includes relationships columns", async () => {
380
+ const otherTable = await new TableConfig("linkedTable")
381
+ .withField("id", FieldType.NUMBER)
382
+ .withField("formula", FieldType.FORMULA)
383
+ .withPrimary("id")
384
+ .create()
385
+
386
+ const table = await new TableConfig("table")
387
+ .withRelation("link", otherTable._id!)
388
+ .create()
389
+
390
+ const view = await new ViewConfig(table)
391
+ .withVisible("name")
392
+ .withVisible("link")
393
+ .withRelationshipColumns("link", {
394
+ name: { visible: false },
395
+ amount: { visible: true },
396
+ formula: { visible: false },
397
+ })
398
+ .create()
399
+
400
+ const result = await buildSqlFieldListInApp(view, allTables, {
401
+ relationships: true,
402
+ })
403
+ expect(result).toEqual([
404
+ "table.name",
405
+ "table.id",
406
+ "linkedTable.id",
407
+ "linkedTable.amount",
408
+ ])
409
+ })
410
+
411
+ it("excludes relationships fields when view is not included in the view", async () => {
412
+ const otherTable = await new TableConfig("linkedTable")
413
+ .withField("id", FieldType.NUMBER)
414
+ .withPrimary("id")
415
+ .withDisplay("name")
416
+ .create()
417
+
418
+ const table = await new TableConfig("table")
419
+ .withRelation("link", otherTable._id!)
420
+ .withField("formula", FieldType.FORMULA)
421
+ .create()
422
+
423
+ const view = await new ViewConfig(table)
424
+ .withVisible("name")
425
+ .withHidden("amount")
426
+ .create()
427
+
428
+ const result = await buildSqlFieldListInApp(view, allTables, {
429
+ relationships: true,
430
+ })
431
+ expect(result).toEqual(["table.name", "table.id"])
437
432
  })
438
- .create()
439
433
 
440
- const result = await buildSqlFieldList(view, allTables, {
441
- relationships: true,
434
+ it("does not include relationships columns for hidden links", async () => {
435
+ const otherTable = await new TableConfig("linkedTable")
436
+ .withField("id", FieldType.NUMBER)
437
+ .withField("formula", FieldType.FORMULA)
438
+ .withPrimary("id")
439
+ .create()
440
+
441
+ const table = await new TableConfig("table")
442
+ .withRelation("link", otherTable._id!)
443
+ .create()
444
+
445
+ const view = await new ViewConfig(table)
446
+ .withVisible("name")
447
+ .withHidden("link")
448
+ .withRelationshipColumns("link", {
449
+ name: { visible: false },
450
+ amount: { visible: true },
451
+ formula: { visible: false },
452
+ })
453
+ .create()
454
+
455
+ const result = await buildSqlFieldListInApp(view, allTables, {
456
+ relationships: true,
457
+ })
458
+ expect(result).toEqual(["table.name", "table.id"])
459
+ })
460
+
461
+ it("includes all relationship fields if there is a formula column", async () => {
462
+ const otherTable = await new TableConfig("linkedTable")
463
+ .withField("id", FieldType.NUMBER)
464
+ .withField("hidden", FieldType.STRING, { visible: false })
465
+ .withField("formula", FieldType.FORMULA)
466
+ .withField("ai", FieldType.AI)
467
+ .withPrimary("id")
468
+ .create()
469
+
470
+ const table = await new TableConfig("table")
471
+ .withRelation("link", otherTable._id!)
472
+ .withField("formula", FieldType.FORMULA)
473
+ .create()
474
+
475
+ const view = await new ViewConfig(table)
476
+ .withVisible("name")
477
+ .withVisible("formula")
478
+ .withHidden("link")
479
+ .withRelationshipColumns("link", {
480
+ name: { visible: false },
481
+ amount: { visible: true },
482
+ formula: { visible: false },
483
+ })
484
+ .create()
485
+
486
+ const result = await buildSqlFieldListInApp(view, allTables, {
487
+ relationships: true,
488
+ })
489
+ expect(result).toEqual([
490
+ "table.name",
491
+ "table.description",
492
+ "table.amount",
493
+ "table.id",
494
+ "linkedTable.name",
495
+ "linkedTable.description",
496
+ "linkedTable.amount",
497
+ "linkedTable.id",
498
+ "linkedTable.hidden",
499
+ ])
500
+ })
442
501
  })
443
- expect(result).toEqual(["table.name"])
444
- })
445
-
446
- it("includes all relationship fields if there is a formula column", async () => {
447
- const otherTable = new TableConfig("linkedTable")
448
- .withField("id", FieldType.NUMBER)
449
- .withField("hidden", FieldType.STRING, { visible: false })
450
- .withField("formula", FieldType.FORMULA)
451
- .withField("ai", FieldType.AI)
452
- .withRelation("link", "otherTableId")
453
- .withPrimary("id")
454
- .create()
455
-
456
- const table = new TableConfig("table")
457
- .withRelation("link", otherTable._id)
458
- .withField("formula", FieldType.FORMULA)
459
- .create()
460
-
461
- const view = new ViewConfig(table)
462
- .withVisible("name")
463
- .withVisible("formula")
464
- .withHidden("link")
465
- .withRelationshipColumns("link", {
466
- name: { visible: false },
467
- amount: { visible: true },
468
- formula: { visible: false },
502
+
503
+ describe("calculation view", () => {
504
+ it("does not include calculation fields", async () => {
505
+ const view = await new ViewConfig(
506
+ await new TableConfig("table").create()
507
+ )
508
+ .withCalculation("average", "amount", CalculationType.AVG)
509
+
510
+ .create()
511
+
512
+ const result = await buildSqlFieldListInApp(view, {})
513
+ expect(result).toEqual([])
469
514
  })
470
- .create()
471
515
 
472
- const result = await buildSqlFieldList(view, allTables, {
473
- relationships: true,
516
+ it("includes visible fields calculation fields", async () => {
517
+ const view = await new ViewConfig(
518
+ await new TableConfig("table").create()
519
+ )
520
+ .withCalculation("average", "amount", CalculationType.AVG)
521
+ .withHidden("name")
522
+ .withVisible("amount")
523
+
524
+ .create()
525
+
526
+ const result = await buildSqlFieldListInApp(view, {})
527
+ expect(result).toEqual(["table.amount"])
528
+ })
474
529
  })
475
- expect(result).toEqual([
476
- "table.name",
477
- "table.description",
478
- "table.amount",
479
- "linkedTable.name",
480
- "linkedTable.description",
481
- "linkedTable.amount",
482
- "linkedTable.id",
483
- "linkedTable.hidden",
484
- ])
485
- })
486
- })
487
-
488
- describe("calculation view", () => {
489
- it("does not include calculation fields", async () => {
490
- const view = new ViewConfig(new TableConfig("table").create())
491
- .withCalculation("average", "amount", CalculationType.AVG)
492
-
493
- .create()
494
-
495
- const result = await buildSqlFieldList(view, {})
496
- expect(result).toEqual([])
497
- })
498
-
499
- it("includes visible fields calculation fields", async () => {
500
- const view = new ViewConfig(new TableConfig("table").create())
501
- .withCalculation("average", "amount", CalculationType.AVG)
502
- .withHidden("name")
503
- .withVisible("amount")
504
-
505
- .create()
506
-
507
- const result = await buildSqlFieldList(view, {})
508
- expect(result).toEqual(["table.amount"])
509
- })
510
- })
511
- })
530
+ }
531
+ )
532
+ }