@budibase/frontend-core 3.2.29 → 3.2.30

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.
Files changed (106) hide show
  1. package/package.json +9 -3
  2. package/src/api/ai.ts +17 -0
  3. package/src/api/analytics.ts +39 -0
  4. package/src/api/{app.js → app.ts} +84 -5
  5. package/src/api/attachments.ts +121 -0
  6. package/src/api/auditLogs.ts +35 -0
  7. package/src/api/{auth.js → auth.ts} +44 -7
  8. package/src/api/automations.ts +158 -0
  9. package/src/api/backups.ts +50 -0
  10. package/src/api/{configs.js → configs.ts} +31 -3
  11. package/src/api/datasources.ts +132 -0
  12. package/src/api/environmentVariables.ts +58 -0
  13. package/src/api/events.ts +21 -0
  14. package/src/api/flags.ts +48 -0
  15. package/src/api/{groups.js → groups.ts} +73 -17
  16. package/src/api/{index.js → index.ts} +89 -102
  17. package/src/api/layouts.ts +35 -0
  18. package/src/api/licensing.ts +107 -0
  19. package/src/api/{logs.js → logs.ts} +7 -1
  20. package/src/api/migrations.ts +19 -0
  21. package/src/api/{other.js → other.ts} +19 -12
  22. package/src/api/{permissions.js → permissions.ts} +31 -5
  23. package/src/api/{plugins.js → plugins.ts} +18 -1
  24. package/src/api/{queries.js → queries.ts} +39 -14
  25. package/src/api/relationships.ts +31 -0
  26. package/src/api/{roles.js → roles.ts} +22 -5
  27. package/src/api/routes.ts +30 -0
  28. package/src/api/{rowActions.js → rowActions.ts} +45 -27
  29. package/src/api/rows.ts +120 -0
  30. package/src/api/screens.ts +35 -0
  31. package/src/api/{self.js → self.ts} +20 -4
  32. package/src/api/tables.ts +192 -0
  33. package/src/api/templates.ts +57 -0
  34. package/src/api/types.ts +136 -0
  35. package/src/api/{user.js → user.ts} +111 -119
  36. package/src/api/{views.js → views.ts} +18 -7
  37. package/src/api/{viewsV2.js → viewsV2.ts} +30 -27
  38. package/src/components/grid/cells/AICell.svelte +1 -0
  39. package/src/components/grid/cells/LongFormCell.svelte +1 -0
  40. package/src/components/grid/cells/RelationshipCell.svelte +1 -2
  41. package/src/components/grid/cells/TextCell.svelte +3 -0
  42. package/src/components/grid/controls/MigrationModal.svelte +5 -5
  43. package/src/components/grid/layout/Grid.svelte +5 -8
  44. package/src/components/grid/lib/constants.js +1 -1
  45. package/src/components/grid/lib/{events.js → events.ts} +3 -3
  46. package/src/components/grid/lib/utils.js +2 -0
  47. package/src/components/grid/lib/utils.ts +32 -0
  48. package/src/components/grid/stores/bounds.ts +29 -0
  49. package/src/components/grid/stores/{cache.js → cache.ts} +21 -6
  50. package/src/components/grid/stores/{clipboard.js → clipboard.ts} +55 -19
  51. package/src/components/grid/stores/{columns.js → columns.ts} +47 -19
  52. package/src/components/grid/stores/{conditions.js → conditions.ts} +32 -12
  53. package/src/components/grid/stores/{config.js → config.ts} +16 -6
  54. package/src/components/grid/stores/{datasource.js → datasource.ts} +86 -36
  55. package/src/components/grid/stores/datasources/index.ts +31 -0
  56. package/src/components/grid/stores/datasources/{nonPlus.js → nonPlus.ts} +21 -11
  57. package/src/components/grid/stores/datasources/{table.js → table.ts} +39 -21
  58. package/src/components/grid/stores/datasources/{viewV2.js → viewV2.ts} +74 -28
  59. package/src/components/grid/stores/{filter.js → filter.ts} +39 -16
  60. package/src/components/grid/stores/index.ts +143 -0
  61. package/src/components/grid/stores/{menu.js → menu.ts} +31 -6
  62. package/src/components/grid/stores/{notifications.js → notifications.ts} +12 -2
  63. package/src/components/grid/stores/{pagination.js → pagination.ts} +2 -1
  64. package/src/components/grid/stores/{reorder.js → reorder.ts} +47 -15
  65. package/src/components/grid/stores/{resize.js → resize.ts} +28 -10
  66. package/src/components/grid/stores/{rows.js → rows.ts} +167 -53
  67. package/src/components/grid/stores/{scroll.js → scroll.ts} +28 -5
  68. package/src/components/grid/stores/{sort.js → sort.ts} +13 -3
  69. package/src/components/grid/stores/{ui.js → ui.ts} +77 -20
  70. package/src/components/grid/stores/{users.js → users.ts} +36 -9
  71. package/src/components/grid/stores/{validation.js → validation.ts} +35 -12
  72. package/src/components/grid/stores/{viewport.js → viewport.ts} +14 -3
  73. package/src/{constants.js → constants.ts} +2 -2
  74. package/src/fetch/QueryFetch.js +2 -2
  75. package/src/fetch/RelationshipFetch.js +9 -6
  76. package/src/fetch/TableFetch.js +1 -2
  77. package/src/fetch/ViewFetch.js +1 -1
  78. package/src/fetch/ViewV2Fetch.js +1 -2
  79. package/src/utils/memo.d.ts +10 -0
  80. package/src/utils/relatedColumns.ts +126 -0
  81. package/tsconfig.json +14 -0
  82. package/src/api/ai.js +0 -11
  83. package/src/api/analytics.js +0 -17
  84. package/src/api/attachments.js +0 -78
  85. package/src/api/auditLogs.js +0 -63
  86. package/src/api/automations.js +0 -111
  87. package/src/api/backups.js +0 -46
  88. package/src/api/datasources.js +0 -92
  89. package/src/api/environmentVariables.js +0 -36
  90. package/src/api/events.js +0 -13
  91. package/src/api/flags.js +0 -34
  92. package/src/api/hosting.js +0 -19
  93. package/src/api/layouts.js +0 -23
  94. package/src/api/licensing.js +0 -75
  95. package/src/api/migrations.js +0 -10
  96. package/src/api/relationships.js +0 -21
  97. package/src/api/routes.js +0 -19
  98. package/src/api/rows.js +0 -117
  99. package/src/api/screens.js +0 -23
  100. package/src/api/tables.js +0 -152
  101. package/src/api/templates.js +0 -35
  102. package/src/components/grid/stores/bounds.js +0 -16
  103. package/src/components/grid/stores/index.js +0 -73
  104. package/src/utils/relatedColumns.js +0 -103
  105. /package/src/{index.js → index.ts} +0 -0
  106. /package/src/utils/{index.js → index.ts} +0 -0
@@ -1,4 +1,4 @@
1
- import { writable, get, derived } from "svelte/store"
1
+ import { writable, get, derived, Writable, Readable } from "svelte/store"
2
2
  import { tick } from "svelte"
3
3
  import {
4
4
  DefaultRowHeight,
@@ -7,8 +7,61 @@ import {
7
7
  NewRowID,
8
8
  } from "../lib/constants"
9
9
  import { getCellID, parseCellID } from "../lib/utils"
10
+ import { Store as StoreContext } from "."
11
+ import { Row } from "@budibase/types"
12
+
13
+ export interface UIStore {
14
+ focusedCellId: Writable<string | null>
15
+ focusedCellAPI: Writable<{
16
+ isReadonly: () => boolean
17
+ getValue: () => any
18
+ setValue: (val: any) => void
19
+ } | null>
20
+ selectedRows: Writable<Record<string, boolean>>
21
+ hoveredRowId: Writable<string | null>
22
+ rowHeight: Writable<number>
23
+ previousFocusedRowId: Writable<string | null>
24
+ previousFocusedCellId: Writable<string | null>
25
+ gridFocused: Writable<boolean>
26
+ keyboardBlocked: Writable<boolean>
27
+ isDragging: Writable<boolean>
28
+ buttonColumnWidth: Writable<number>
29
+ cellSelection: Writable<{
30
+ active: boolean
31
+ sourceCellId: string | null
32
+ targetCellId: string | null
33
+ }>
34
+ }
35
+
36
+ export interface UIDerivedStore {
37
+ focusedRowId: Readable<string | null>
38
+ focusedRow: Readable<Row | undefined>
39
+ contentLines: Readable<3 | 2 | 1>
40
+ compact: Readable<boolean>
41
+ selectedRowCount: Readable<number>
42
+ isSelectingCells: Readable<boolean>
43
+ selectedCells: Readable<string[][]>
44
+ selectedCellMap: Readable<Record<string, boolean>>
45
+ selectedCellCount: Readable<number>
46
+ }
47
+
48
+ interface UIActionStore {
49
+ selectedCells: UIDerivedStore["selectedCells"] & {
50
+ actions: {
51
+ clear: () => void
52
+ selectRange: (source: string | null, target: string | null) => void
53
+ }
54
+ }
55
+ ui: {
56
+ actions: {
57
+ blur: () => void
58
+ }
59
+ }
60
+ }
10
61
 
11
- export const createStores = context => {
62
+ export type Store = UIStore & UIDerivedStore & UIActionStore
63
+
64
+ export const createStores = (context: StoreContext): UIStore => {
12
65
  const { props } = context
13
66
  const focusedCellId = writable(null)
14
67
  const focusedCellAPI = writable(null)
@@ -43,7 +96,7 @@ export const createStores = context => {
43
96
  }
44
97
  }
45
98
 
46
- export const deriveStores = context => {
99
+ export const deriveStores = (context: StoreContext): UIDerivedStore => {
47
100
  const {
48
101
  focusedCellId,
49
102
  rows,
@@ -58,13 +111,17 @@ export const deriveStores = context => {
58
111
 
59
112
  // Derive the current focused row ID
60
113
  const focusedRowId = derived(focusedCellId, $focusedCellId => {
61
- return parseCellID($focusedCellId).rowId
114
+ return parseCellID($focusedCellId).rowId ?? null
62
115
  })
63
116
 
64
117
  // Derive the row that contains the selected cell
65
118
  const focusedRow = derived(
66
119
  [focusedRowId, rowLookupMap],
67
120
  ([$focusedRowId, $rowLookupMap]) => {
121
+ if ($focusedRowId === null) {
122
+ return
123
+ }
124
+
68
125
  if ($focusedRowId === NewRowID) {
69
126
  return { _id: NewRowID }
70
127
  }
@@ -116,8 +173,8 @@ export const deriveStores = context => {
116
173
  }
117
174
 
118
175
  // Row indices
119
- const sourceRowIndex = $rowLookupMap[sourceInfo.rowId]?.__idx
120
- const targetRowIndex = $rowLookupMap[targetInfo.rowId]?.__idx
176
+ const sourceRowIndex = $rowLookupMap[sourceInfo.rowId!]?.__idx
177
+ const targetRowIndex = $rowLookupMap[targetInfo.rowId!]?.__idx
121
178
  if (sourceRowIndex == null || targetRowIndex == null) {
122
179
  return []
123
180
  }
@@ -128,8 +185,8 @@ export const deriveStores = context => {
128
185
  upperRowIndex = Math.min(upperRowIndex, lowerRowIndex + 49)
129
186
 
130
187
  // Column indices
131
- const sourceColIndex = $columnLookupMap[sourceInfo.field].__idx
132
- const targetColIndex = $columnLookupMap[targetInfo.field].__idx
188
+ const sourceColIndex = $columnLookupMap[sourceInfo.field!].__idx || 0
189
+ const targetColIndex = $columnLookupMap[targetInfo.field!].__idx || 0
133
190
  const lowerColIndex = Math.min(sourceColIndex, targetColIndex)
134
191
  const upperColIndex = Math.max(sourceColIndex, targetColIndex)
135
192
 
@@ -151,7 +208,7 @@ export const deriveStores = context => {
151
208
 
152
209
  // Derive a quick lookup map of the selected cells
153
210
  const selectedCellMap = derived(selectedCells, $selectedCells => {
154
- let map = {}
211
+ let map: Record<string, boolean> = {}
155
212
  for (let row of $selectedCells) {
156
213
  for (let cell of row) {
157
214
  map[cell] = true
@@ -178,7 +235,7 @@ export const deriveStores = context => {
178
235
  }
179
236
  }
180
237
 
181
- export const createActions = context => {
238
+ export const createActions = (context: StoreContext) => {
182
239
  const {
183
240
  focusedCellId,
184
241
  hoveredRowId,
@@ -190,7 +247,7 @@ export const createActions = context => {
190
247
  selectedCells,
191
248
  } = context
192
249
  // Keep the last selected index to use with bulk selection
193
- let lastSelectedIndex = null
250
+ let lastSelectedIndex: number | null = null
194
251
 
195
252
  // Callback when leaving the grid, deselecting all focussed or selected items
196
253
  const blur = () => {
@@ -200,7 +257,7 @@ export const createActions = context => {
200
257
  }
201
258
 
202
259
  // Toggles whether a certain row ID is selected or not
203
- const toggleSelectedRow = id => {
260
+ const toggleSelectedRow = (id: string) => {
204
261
  selectedRows.update(state => {
205
262
  let newState = {
206
263
  ...state,
@@ -215,7 +272,7 @@ export const createActions = context => {
215
272
  })
216
273
  }
217
274
 
218
- const bulkSelectRows = id => {
275
+ const bulkSelectRows = (id: string) => {
219
276
  if (!get(selectedRowCount)) {
220
277
  toggleSelectedRow(id)
221
278
  return
@@ -241,7 +298,7 @@ export const createActions = context => {
241
298
  })
242
299
  }
243
300
 
244
- const startCellSelection = sourceCellId => {
301
+ const startCellSelection = (sourceCellId: string) => {
245
302
  cellSelection.set({
246
303
  active: true,
247
304
  sourceCellId,
@@ -249,7 +306,7 @@ export const createActions = context => {
249
306
  })
250
307
  }
251
308
 
252
- const updateCellSelection = targetCellId => {
309
+ const updateCellSelection = (targetCellId: string) => {
253
310
  cellSelection.update(state => ({
254
311
  ...state,
255
312
  targetCellId,
@@ -263,7 +320,7 @@ export const createActions = context => {
263
320
  }))
264
321
  }
265
322
 
266
- const selectCellRange = (source, target) => {
323
+ const selectCellRange = (source: string, target: string) => {
267
324
  cellSelection.set({
268
325
  active: false,
269
326
  sourceCellId: source,
@@ -305,7 +362,7 @@ export const createActions = context => {
305
362
  }
306
363
  }
307
364
 
308
- export const initialise = context => {
365
+ export const initialise = (context: StoreContext) => {
309
366
  const {
310
367
  focusedRowId,
311
368
  previousFocusedRowId,
@@ -332,7 +389,7 @@ export const initialise = context => {
332
389
  const $focusedRowId = get(focusedRowId)
333
390
  const $selectedRows = get(selectedRows)
334
391
  const $hoveredRowId = get(hoveredRowId)
335
- const hasRow = id => $rowLookupMap[id] != null
392
+ const hasRow = (id: string) => $rowLookupMap[id] != null
336
393
 
337
394
  // Check focused cell
338
395
  if ($focusedRowId && !hasRow($focusedRowId)) {
@@ -362,13 +419,13 @@ export const initialise = context => {
362
419
  })
363
420
 
364
421
  // Remember the last focused row ID so that we can store the previous one
365
- let lastFocusedRowId = null
422
+ let lastFocusedRowId: string | null = null
366
423
  focusedRowId.subscribe(id => {
367
424
  previousFocusedRowId.set(lastFocusedRowId)
368
425
  lastFocusedRowId = id
369
426
  })
370
427
 
371
- let lastFocusedCellId = null
428
+ let lastFocusedCellId: string | null = null
372
429
  focusedCellId.subscribe(id => {
373
430
  // Remember the last focused cell ID so that we can store the previous one
374
431
  previousFocusedCellId.set(lastFocusedCellId)
@@ -1,11 +1,38 @@
1
- import { writable, get, derived } from "svelte/store"
1
+ import { writable, get, derived, Writable, Readable } from "svelte/store"
2
2
  import { helpers } from "@budibase/shared-core"
3
+ import { Store as StoreContext } from "."
4
+ import { UIUser } from "@budibase/types"
3
5
 
4
- export const createStores = () => {
5
- const users = writable([])
6
+ interface UIEnrichedUser extends UIUser {
7
+ color: string
8
+ label: string
9
+ }
10
+
11
+ interface UsersStore {
12
+ users: Writable<UIUser[]>
13
+ }
14
+
15
+ interface DerivedUsersStore {
16
+ userCellMap: Readable<Record<string, UIUser>>
17
+ }
18
+
19
+ interface ActionUserStore {
20
+ users: UsersStore["users"] &
21
+ Readable<UIEnrichedUser[]> & {
22
+ actions: {
23
+ updateUser: (user: UIUser) => void
24
+ removeUser: (sessionId: string) => void
25
+ }
26
+ }
27
+ }
28
+
29
+ export type Store = DerivedUsersStore & ActionUserStore
30
+
31
+ export const createStores = (): UsersStore => {
32
+ const users = writable<UIUser[]>([])
6
33
 
7
34
  const enrichedUsers = derived(users, $users => {
8
- return $users.map(user => ({
35
+ return $users.map<UIEnrichedUser>(user => ({
9
36
  ...user,
10
37
  color: helpers.getUserColor(user),
11
38
  label: helpers.getUserLabel(user),
@@ -20,7 +47,7 @@ export const createStores = () => {
20
47
  }
21
48
  }
22
49
 
23
- export const deriveStores = context => {
50
+ export const deriveStores = (context: StoreContext): DerivedUsersStore => {
24
51
  const { users, focusedCellId } = context
25
52
 
26
53
  // Generate a lookup map of cell ID to the user that has it selected, to make
@@ -28,7 +55,7 @@ export const deriveStores = context => {
28
55
  const userCellMap = derived(
29
56
  [users, focusedCellId],
30
57
  ([$users, $focusedCellId]) => {
31
- let map = {}
58
+ let map: Record<string, UIUser> = {}
32
59
  $users.forEach(user => {
33
60
  const cellId = user.gridMetadata?.focusedCellId
34
61
  if (cellId && cellId !== $focusedCellId) {
@@ -44,10 +71,10 @@ export const deriveStores = context => {
44
71
  }
45
72
  }
46
73
 
47
- export const createActions = context => {
74
+ export const createActions = (context: StoreContext): ActionUserStore => {
48
75
  const { users } = context
49
76
 
50
- const updateUser = user => {
77
+ const updateUser = (user: UIUser) => {
51
78
  const $users = get(users)
52
79
  if (!$users.some(x => x.sessionId === user.sessionId)) {
53
80
  users.set([...$users, user])
@@ -60,7 +87,7 @@ export const createActions = context => {
60
87
  }
61
88
  }
62
89
 
63
- const removeUser = sessionId => {
90
+ const removeUser = (sessionId: string) => {
64
91
  users.update(state => {
65
92
  return state.filter(x => x.sessionId !== sessionId)
66
93
  })
@@ -1,10 +1,31 @@
1
- import { writable, get, derived } from "svelte/store"
1
+ import { writable, get, derived, Writable, Readable } from "svelte/store"
2
+ import { Store as StoreContext } from "."
2
3
  import { parseCellID } from "../lib/utils"
3
4
 
5
+ interface ValidationStore {
6
+ validation: Writable<Record<string, string>>
7
+ }
8
+
9
+ interface DerivedValidationStore {
10
+ validationRowLookupMap: Readable<Record<string, string[]>>
11
+ }
12
+
13
+ interface ValidationActions {
14
+ validation: ValidationStore["validation"] & {
15
+ actions: {
16
+ setError: (cellId: string | undefined, error: string) => void
17
+ rowHasErrors: (rowId: string) => boolean
18
+ focusFirstRowError: (rowId: string) => void
19
+ }
20
+ }
21
+ }
22
+
23
+ export type Store = ValidationStore & DerivedValidationStore & ValidationActions
24
+
4
25
  // Normally we would break out actions into the explicit "createActions"
5
26
  // function, but for validation all these actions are pure so can go into
6
27
  // "createStores" instead to make dependency ordering simpler
7
- export const createStores = () => {
28
+ export const createStores = (): ValidationStore => {
8
29
  const validation = writable({})
9
30
 
10
31
  return {
@@ -12,20 +33,22 @@ export const createStores = () => {
12
33
  }
13
34
  }
14
35
 
15
- export const deriveStores = context => {
36
+ export const deriveStores = (context: StoreContext): DerivedValidationStore => {
16
37
  const { validation } = context
17
38
 
18
39
  // Derive which rows have errors so that we can use that info later
19
40
  const validationRowLookupMap = derived(validation, $validation => {
20
- let map = {}
41
+ const map: Record<string, string[]> = {}
21
42
  Object.entries($validation).forEach(([key, error]) => {
22
43
  // Extract row ID from all errored cell IDs
23
44
  if (error) {
24
45
  const { rowId } = parseCellID(key)
25
- if (!map[rowId]) {
26
- map[rowId] = []
46
+ if (rowId !== undefined) {
47
+ if (!map[rowId]) {
48
+ map[rowId] = []
49
+ }
50
+ map[rowId].push(key)
27
51
  }
28
- map[rowId].push(key)
29
52
  }
30
53
  })
31
54
  return map
@@ -36,10 +59,10 @@ export const deriveStores = context => {
36
59
  }
37
60
  }
38
61
 
39
- export const createActions = context => {
62
+ export const createActions = (context: StoreContext): ValidationActions => {
40
63
  const { validation, focusedCellId, validationRowLookupMap } = context
41
64
 
42
- const setError = (cellId, error) => {
65
+ const setError = (cellId: string | undefined, error: string) => {
43
66
  if (!cellId) {
44
67
  return
45
68
  }
@@ -49,11 +72,11 @@ export const createActions = context => {
49
72
  }))
50
73
  }
51
74
 
52
- const rowHasErrors = rowId => {
75
+ const rowHasErrors = (rowId: string) => {
53
76
  return get(validationRowLookupMap)[rowId]?.length > 0
54
77
  }
55
78
 
56
- const focusFirstRowError = rowId => {
79
+ const focusFirstRowError = (rowId: string) => {
57
80
  const errorCells = get(validationRowLookupMap)[rowId]
58
81
  const cellId = errorCells?.[0]
59
82
  if (cellId) {
@@ -73,7 +96,7 @@ export const createActions = context => {
73
96
  }
74
97
  }
75
98
 
76
- export const initialise = context => {
99
+ export const initialise = (context: StoreContext) => {
77
100
  const { validation, previousFocusedRowId, validationRowLookupMap } = context
78
101
 
79
102
  // Remove validation errors when changing rows
@@ -1,7 +1,18 @@
1
- import { derived } from "svelte/store"
1
+ import { derived, Readable } from "svelte/store"
2
2
  import { MinColumnWidth } from "../lib/constants"
3
+ import { Store as StoreContext } from "."
4
+ import { Row } from "@budibase/types"
3
5
 
4
- export const deriveStores = context => {
6
+ interface ViewportDerivedStore {
7
+ scrolledRowCount: Readable<number>
8
+ visualRowCapacity: Readable<number>
9
+ renderedRows: Readable<Row>
10
+ columnRenderMap: Readable<Record<string, true>>
11
+ }
12
+
13
+ export type Store = ViewportDerivedStore
14
+
15
+ export const deriveStores = (context: StoreContext): ViewportDerivedStore => {
5
16
  const {
6
17
  rowHeight,
7
18
  scrollableColumns,
@@ -77,7 +88,7 @@ export const deriveStores = context => {
77
88
  leftEdge += $scrollableColumns[endColIdx].width
78
89
  endColIdx++
79
90
  }
80
- let next = {}
91
+ let next: Record<string, true> = {}
81
92
  $scrollableColumns
82
93
  .slice(Math.max(0, startColIdx), endColIdx)
83
94
  .forEach(col => {
@@ -76,9 +76,9 @@ export const ExtendedBudibaseRoleOptions = [
76
76
  value: BudibaseRoles.Owner,
77
77
  sortOrder: 0,
78
78
  },
79
+ ...BudibaseRoleOptions,
80
+ ...BudibaseRoleOptionsOld,
79
81
  ]
80
- .concat(BudibaseRoleOptions)
81
- .concat(BudibaseRoleOptionsOld)
82
82
 
83
83
  export const PlanType = {
84
84
  FREE: "free",
@@ -48,7 +48,7 @@ export default class QueryFetch extends DataFetch {
48
48
  }
49
49
 
50
50
  // Add pagination to query if supported
51
- let queryPayload = { queryId: datasource?._id, parameters }
51
+ let queryPayload = { parameters }
52
52
  if (paginate && supportsPagination) {
53
53
  const requestCursor = type === "page" ? parseInt(cursor || 1) : cursor
54
54
  queryPayload.pagination = { page: requestCursor, limit }
@@ -56,7 +56,7 @@ export default class QueryFetch extends DataFetch {
56
56
 
57
57
  // Execute query
58
58
  try {
59
- const res = await this.API.executeQuery(queryPayload)
59
+ const res = await this.API.executeQuery(datasource?._id, queryPayload)
60
60
  const { data, pagination, ...rest } = res
61
61
 
62
62
  // Derive pagination info from response
@@ -3,13 +3,16 @@ import DataFetch from "./DataFetch.js"
3
3
  export default class RelationshipFetch extends DataFetch {
4
4
  async getData() {
5
5
  const { datasource } = this.options
6
+ if (!datasource?.rowId || !datasource?.rowTableId) {
7
+ return { rows: [] }
8
+ }
6
9
  try {
7
- const res = await this.API.fetchRelationshipData({
8
- rowId: datasource?.rowId,
9
- tableId: datasource?.rowTableId,
10
- fieldName: datasource?.fieldName,
11
- })
12
- return { rows: res || [] }
10
+ const res = await this.API.fetchRelationshipData(
11
+ datasource.rowTableId,
12
+ datasource.rowId,
13
+ datasource.fieldName
14
+ )
15
+ return { rows: res }
13
16
  } catch (error) {
14
17
  return { rows: [] }
15
18
  }
@@ -19,8 +19,7 @@ export default class TableFetch extends DataFetch {
19
19
 
20
20
  // Search table
21
21
  try {
22
- const res = await this.API.searchTable({
23
- tableId,
22
+ const res = await this.API.searchTable(tableId, {
24
23
  query,
25
24
  limit,
26
25
  sort: sortColumn,
@@ -8,7 +8,7 @@ export default class ViewFetch extends DataFetch {
8
8
  async getData() {
9
9
  const { datasource } = this.options
10
10
  try {
11
- const res = await this.API.fetchViewData(datasource)
11
+ const res = await this.API.fetchViewData(datasource.name)
12
12
  return { rows: res || [] }
13
13
  } catch (error) {
14
14
  return { rows: [] }
@@ -62,8 +62,7 @@ export default class ViewV2Fetch extends DataFetch {
62
62
  }
63
63
 
64
64
  try {
65
- const res = await this.API.viewV2.fetch({
66
- viewId: datasource.id,
65
+ const res = await this.API.viewV2.fetch(datasource.id, {
67
66
  ...(query ? { query } : {}),
68
67
  paginate,
69
68
  limit,
@@ -0,0 +1,10 @@
1
+ import { Readable, Writable } from "svelte/store"
2
+
3
+ declare module "./memo" {
4
+ export function memo<T>(value: T): Writable<T>
5
+
6
+ export function derivedMemo<TStore, TResult>(
7
+ store: Readable<TStore>,
8
+ derivation: (store: TStore) => TResult
9
+ ): Readable<TResult>
10
+ }
@@ -0,0 +1,126 @@
1
+ import { Helpers } from "@budibase/bbui"
2
+ import {
3
+ FieldType,
4
+ isRelationshipField,
5
+ RelationshipType,
6
+ Row,
7
+ UIFieldSchema,
8
+ } from "@budibase/types"
9
+
10
+ const columnTypeManyTypeOverrides: Partial<Record<FieldType, FieldType>> = {
11
+ [FieldType.DATETIME]: FieldType.STRING,
12
+ [FieldType.BOOLEAN]: FieldType.STRING,
13
+ [FieldType.SIGNATURE_SINGLE]: FieldType.ATTACHMENTS,
14
+ }
15
+
16
+ const columnTypeManyParser = {
17
+ [FieldType.DATETIME]: (
18
+ value: any[],
19
+ field: {
20
+ timeOnly?: boolean
21
+ dateOnly?: boolean
22
+ }
23
+ ) => {
24
+ function parseDate(value: any) {
25
+ const { timeOnly, dateOnly } = field || {}
26
+ const enableTime = !dateOnly
27
+ const parsedValue = Helpers.parseDate(value, { enableTime })
28
+ const parsed = Helpers.getDateDisplayValue(parsedValue, {
29
+ enableTime,
30
+ timeOnly,
31
+ })
32
+ return parsed
33
+ }
34
+
35
+ return value.map(v => parseDate(v))
36
+ },
37
+ [FieldType.BOOLEAN]: (value: any[]) => value.map(v => !!v),
38
+ [FieldType.BB_REFERENCE_SINGLE]: (value: any[]) => [
39
+ ...new Map(value.map(i => [i._id, i])).values(),
40
+ ],
41
+ [FieldType.BB_REFERENCE]: (value: any[]) => [
42
+ ...new Map(value.map(i => [i._id, i])).values(),
43
+ ],
44
+ [FieldType.ARRAY]: (value: any[]) => Array.from(new Set(value)),
45
+ }
46
+
47
+ export function enrichSchemaWithRelColumns(
48
+ schema: Record<string, UIFieldSchema>
49
+ ): Record<string, UIFieldSchema> {
50
+ const result = Object.keys(schema).reduce<Record<string, UIFieldSchema>>(
51
+ (result, fieldName) => {
52
+ const field = schema[fieldName]
53
+ result[fieldName] = field
54
+
55
+ if (
56
+ field.visible !== false &&
57
+ isRelationshipField(field) &&
58
+ field.columns
59
+ ) {
60
+ const fromSingle =
61
+ field?.relationshipType === RelationshipType.ONE_TO_MANY
62
+
63
+ for (const relColumn of Object.keys(field.columns)) {
64
+ const relField = field.columns[relColumn]
65
+ if (!relField.visible) {
66
+ continue
67
+ }
68
+ const name = `${field.name}.${relColumn}`
69
+ result[name] = {
70
+ ...relField,
71
+ type: relField.type as any, // TODO
72
+ name,
73
+ related: { field: fieldName, subField: relColumn },
74
+ cellRenderType:
75
+ (!fromSingle && columnTypeManyTypeOverrides[relField.type]) ||
76
+ relField.type,
77
+ }
78
+ }
79
+ }
80
+ return result
81
+ },
82
+ {}
83
+ )
84
+
85
+ return result
86
+ }
87
+
88
+ export function getRelatedTableValues(
89
+ row: Row,
90
+ field: UIFieldSchema & { related: { field: string; subField: string } },
91
+ fromField: UIFieldSchema
92
+ ) {
93
+ const fromSingle =
94
+ isRelationshipField(fromField) &&
95
+ fromField?.relationshipType === RelationshipType.ONE_TO_MANY
96
+
97
+ let result = ""
98
+
99
+ if (fromSingle) {
100
+ result = row[field.related.field]?.[0]?.[field.related.subField]
101
+ } else {
102
+ const parser =
103
+ columnTypeManyParser[field.type as keyof typeof columnTypeManyParser] ||
104
+ ((value: any) => value)
105
+ const value = row[field.related.field]
106
+ ?.flatMap((r: Row) => r[field.related.subField])
107
+ ?.filter((i: any) => i !== undefined && i !== null)
108
+ const parsed = parser(value || [], field as any)
109
+ result = parsed as any
110
+ if (
111
+ [
112
+ FieldType.STRING,
113
+ FieldType.NUMBER,
114
+ FieldType.BIGINT,
115
+ FieldType.BOOLEAN,
116
+ FieldType.DATETIME,
117
+ FieldType.LONGFORM,
118
+ FieldType.BARCODEQR,
119
+ ].includes(field.type)
120
+ ) {
121
+ result = parsed?.join(", ")
122
+ }
123
+ }
124
+
125
+ return result
126
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "../../tsconfig.build.json",
3
+ "compilerOptions": {
4
+ "target": "ESNext",
5
+ "lib": ["ESNext"],
6
+ "module": "preserve",
7
+ "moduleResolution": "bundler",
8
+ "outDir": "./dist",
9
+ "skipLibCheck": true,
10
+ "allowJs": true
11
+ },
12
+ "include": ["src/**/*"],
13
+ "exclude": ["node_modules", "dist"]
14
+ }
package/src/api/ai.js DELETED
@@ -1,11 +0,0 @@
1
- export const buildAIEndpoints = API => ({
2
- /**
3
- * Generates a cron expression from a prompt
4
- */
5
- generateCronExpression: async ({ prompt }) => {
6
- return await API.post({
7
- url: "/api/ai/cron",
8
- body: { prompt },
9
- })
10
- },
11
- })