@budibase/server 2.6.19-alpha.47 → 2.6.19-alpha.49

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "2.6.19-alpha.47",
4
+ "version": "2.6.19-alpha.49",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -46,12 +46,12 @@
46
46
  "license": "GPL-3.0",
47
47
  "dependencies": {
48
48
  "@apidevtools/swagger-parser": "10.0.3",
49
- "@budibase/backend-core": "2.6.19-alpha.47",
50
- "@budibase/client": "2.6.19-alpha.47",
51
- "@budibase/pro": "2.6.19-alpha.47",
52
- "@budibase/shared-core": "2.6.19-alpha.47",
53
- "@budibase/string-templates": "2.6.19-alpha.47",
54
- "@budibase/types": "2.6.19-alpha.47",
49
+ "@budibase/backend-core": "2.6.19-alpha.49",
50
+ "@budibase/client": "2.6.19-alpha.49",
51
+ "@budibase/pro": "2.6.19-alpha.49",
52
+ "@budibase/shared-core": "2.6.19-alpha.49",
53
+ "@budibase/string-templates": "2.6.19-alpha.49",
54
+ "@budibase/types": "2.6.19-alpha.49",
55
55
  "@bull-board/api": "3.7.0",
56
56
  "@bull-board/koa": "3.9.4",
57
57
  "@elastic/elasticsearch": "7.10.0",
@@ -195,5 +195,5 @@
195
195
  }
196
196
  }
197
197
  },
198
- "gitHead": "f4e4d3af85182c8f8a3c2cf472f403f92d8395df"
198
+ "gitHead": "9409103d5e82b9023c3020cc861b8ceecaa9f87b"
199
199
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
- SortDirection,
3
2
  FieldTypes,
4
3
  NoEmptyFilterStrings,
4
+ SortDirection,
5
5
  } from "../../../constants"
6
6
  import {
7
7
  breakExternalTableId,
@@ -11,20 +11,34 @@ import { ExternalRequest, RunConfig } from "./ExternalRequest"
11
11
  import * as exporters from "../view/exporters"
12
12
  import { apiFileReturn } from "../../../utilities/fileSystem"
13
13
  import {
14
- Operation,
15
- UserCtx,
16
- Row,
17
- PaginationJson,
18
- Table,
19
14
  Datasource,
20
15
  IncludeRelationship,
16
+ Operation,
17
+ PaginationJson,
18
+ Row,
21
19
  SortJson,
20
+ Table,
21
+ UserCtx,
22
22
  } from "@budibase/types"
23
23
  import sdk from "../../../sdk"
24
24
  import * as utils from "./utils"
25
25
 
26
26
  const { cleanExportRows } = require("./utils")
27
27
 
28
+ async function getRow(
29
+ tableId: string,
30
+ rowId: string,
31
+ opts?: { relationships?: boolean }
32
+ ) {
33
+ const response = (await handleRequest(Operation.READ, tableId, {
34
+ id: breakRowIdField(rowId),
35
+ includeSqlRelationships: opts?.relationships
36
+ ? IncludeRelationship.INCLUDE
37
+ : IncludeRelationship.EXCLUDE,
38
+ })) as Row[]
39
+ return response ? response[0] : response
40
+ }
41
+
28
42
  export async function handleRequest(
29
43
  operation: Operation,
30
44
  tableId: string,
@@ -63,11 +77,15 @@ export async function patch(ctx: UserCtx) {
63
77
  if (!validateResult.valid) {
64
78
  throw { validation: validateResult.errors }
65
79
  }
66
- return handleRequest(Operation.UPDATE, tableId, {
80
+ const response = await handleRequest(Operation.UPDATE, tableId, {
67
81
  id: breakRowIdField(id),
68
82
  row: inputs,
69
- includeSqlRelationships: IncludeRelationship.INCLUDE,
70
83
  })
84
+ const row = await getRow(tableId, id, { relationships: true })
85
+ return {
86
+ ...response,
87
+ row,
88
+ }
71
89
  }
72
90
 
73
91
  export async function save(ctx: UserCtx) {
@@ -80,10 +98,20 @@ export async function save(ctx: UserCtx) {
80
98
  if (!validateResult.valid) {
81
99
  throw { validation: validateResult.errors }
82
100
  }
83
- return handleRequest(Operation.CREATE, tableId, {
101
+ const response = await handleRequest(Operation.CREATE, tableId, {
84
102
  row: inputs,
85
- includeSqlRelationships: IncludeRelationship.EXCLUDE,
86
103
  })
104
+ const responseRow = response as { row: Row }
105
+ const rowId = responseRow.row._id
106
+ if (rowId) {
107
+ const row = await getRow(tableId, rowId, { relationships: true })
108
+ return {
109
+ ...response,
110
+ row,
111
+ }
112
+ } else {
113
+ return response
114
+ }
87
115
  }
88
116
 
89
117
  export async function fetchView(ctx: UserCtx) {
@@ -104,11 +132,7 @@ export async function fetch(ctx: UserCtx) {
104
132
  export async function find(ctx: UserCtx) {
105
133
  const id = ctx.params.rowId
106
134
  const tableId = ctx.params.tableId
107
- const response = (await handleRequest(Operation.READ, tableId, {
108
- id: breakRowIdField(id),
109
- includeSqlRelationships: IncludeRelationship.EXCLUDE,
110
- })) as Row[]
111
- return response ? response[0] : response
135
+ return getRow(tableId, id)
112
136
  }
113
137
 
114
138
  export async function destroy(ctx: UserCtx) {
@@ -50,7 +50,7 @@ export const save = async (ctx: any) => {
50
50
  if (body && body._id) {
51
51
  return patch(ctx)
52
52
  }
53
- const { row, table } = await quotas.addRow(() =>
53
+ const { row, table, squashed } = await quotas.addRow(() =>
54
54
  quotas.addQuery(() => pickApi(tableId).save(ctx), {
55
55
  datasourceId: tableId,
56
56
  })
@@ -58,8 +58,9 @@ export const save = async (ctx: any) => {
58
58
  ctx.status = 200
59
59
  ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:save`, appId, row, table)
60
60
  ctx.message = `${table.name} saved successfully`
61
- ctx.body = row
62
- gridSocket?.emitRowUpdate(ctx, row)
61
+ // prefer squashed for response
62
+ ctx.body = row || squashed
63
+ gridSocket?.emitRowUpdate(ctx, row || squashed)
63
64
  }
64
65
  export async function fetchView(ctx: any) {
65
66
  const tableId = utils.getTableId(ctx)
@@ -7,6 +7,7 @@ import {
7
7
  import { FieldTypes, FormulaTypes } from "../../../constants"
8
8
  import { context } from "@budibase/backend-core"
9
9
  import { Table, Row } from "@budibase/types"
10
+ import * as linkRows from "../../../db/linkedRows"
10
11
  const { isEqual } = require("lodash")
11
12
  const { cloneDeep } = require("lodash/fp")
12
13
 
@@ -166,5 +167,9 @@ export async function finaliseRow(
166
167
  if (updateFormula) {
167
168
  await updateRelatedFormula(table, enrichedRow)
168
169
  }
169
- return { row: enrichedRow, table }
170
+ const squashed = await linkRows.squashLinksToPrimaryDisplay(
171
+ table,
172
+ enrichedRow
173
+ )
174
+ return { row: enrichedRow, squashed, table }
170
175
  }
@@ -189,11 +189,13 @@ export async function attachFullLinkedDocs(table: Table, rows: Row[]) {
189
189
  */
190
190
  export async function squashLinksToPrimaryDisplay(
191
191
  table: Table,
192
- enriched: Row[]
192
+ enriched: Row[] | Row
193
193
  ) {
194
194
  // will populate this as we find them
195
195
  const linkedTables = [table]
196
- for (let row of enriched) {
196
+ const isArray = Array.isArray(enriched)
197
+ let enrichedArray = !isArray ? [enriched] : enriched
198
+ for (let row of enrichedArray) {
197
199
  // this only fetches the table if its not already in array
198
200
  const rowTable = await getLinkedTable(row.tableId!, linkedTables)
199
201
  for (let [column, schema] of Object.entries(rowTable?.schema || {})) {
@@ -213,5 +215,5 @@ export async function squashLinksToPrimaryDisplay(
213
215
  row[column] = newLinks
214
216
  }
215
217
  }
216
- return enriched
218
+ return isArray ? enrichedArray : enrichedArray[0]
217
219
  }
@@ -216,7 +216,10 @@ export async function outputProcessing(
216
216
  }
217
217
  }
218
218
  if (opts.squash) {
219
- enriched = await linkRows.squashLinksToPrimaryDisplay(table, enriched)
219
+ enriched = (await linkRows.squashLinksToPrimaryDisplay(
220
+ table,
221
+ enriched
222
+ )) as Row[]
220
223
  }
221
224
  return wasArray ? enriched : enriched[0]
222
225
  }
@@ -46,29 +46,32 @@ export default class BuilderSocket extends BaseSocket {
46
46
  }
47
47
 
48
48
  emitTableUpdate(ctx: any, table: Table) {
49
- this.io
50
- .in(ctx.appId)
51
- .emit(BuilderSocketEvent.TableChange, { id: table._id, table })
52
- gridSocket?.emitTableUpdate(table)
49
+ this.emitToRoom(ctx, ctx.appId, BuilderSocketEvent.TableChange, {
50
+ id: table._id,
51
+ table,
52
+ })
53
+ gridSocket?.emitTableUpdate(ctx, table)
53
54
  }
54
55
 
55
56
  emitTableDeletion(ctx: any, id: string) {
56
- this.io
57
- .in(ctx.appId)
58
- .emit(BuilderSocketEvent.TableChange, { id, table: null })
59
- gridSocket?.emitTableDeletion(id)
57
+ this.emitToRoom(ctx, ctx.appId, BuilderSocketEvent.TableChange, {
58
+ id,
59
+ table: null,
60
+ })
61
+ gridSocket?.emitTableDeletion(ctx, id)
60
62
  }
61
63
 
62
64
  emitDatasourceUpdate(ctx: any, datasource: Datasource) {
63
- this.io.in(ctx.appId).emit(BuilderSocketEvent.DatasourceChange, {
65
+ this.emitToRoom(ctx, ctx.appId, BuilderSocketEvent.DatasourceChange, {
64
66
  id: datasource._id,
65
67
  datasource,
66
68
  })
67
69
  }
68
70
 
69
71
  emitDatasourceDeletion(ctx: any, id: string) {
70
- this.io
71
- .in(ctx.appId)
72
- .emit(BuilderSocketEvent.DatasourceChange, { id, datasource: null })
72
+ this.emitToRoom(ctx, ctx.appId, BuilderSocketEvent.DatasourceChange, {
73
+ id,
74
+ datasource: null,
75
+ })
73
76
  }
74
77
  }
@@ -31,21 +31,25 @@ export default class GridSocket extends BaseSocket {
31
31
 
32
32
  emitRowUpdate(ctx: any, row: Row) {
33
33
  const tableId = getTableId(ctx)
34
- this.io.in(tableId).emit(GridSocketEvent.RowChange, { id: row._id, row })
34
+ this.emitToRoom(ctx, tableId, GridSocketEvent.RowChange, {
35
+ id: row._id,
36
+ row,
37
+ })
35
38
  }
36
39
 
37
40
  emitRowDeletion(ctx: any, id: string) {
38
41
  const tableId = getTableId(ctx)
39
- this.io.in(tableId).emit(GridSocketEvent.RowChange, { id, row: null })
42
+ this.emitToRoom(ctx, tableId, GridSocketEvent.RowChange, { id, row: null })
40
43
  }
41
44
 
42
- emitTableUpdate(table: Table) {
43
- this.io
44
- .in(table._id!)
45
- .emit(GridSocketEvent.TableChange, { id: table._id, table })
45
+ emitTableUpdate(ctx: any, table: Table) {
46
+ this.emitToRoom(ctx, table._id!, GridSocketEvent.TableChange, {
47
+ id: table._id,
48
+ table,
49
+ })
46
50
  }
47
51
 
48
- emitTableDeletion(id: string) {
49
- this.io.in(id).emit(GridSocketEvent.TableChange, { id, table: null })
52
+ emitTableDeletion(ctx: any, id: string) {
53
+ this.emitToRoom(ctx, id, GridSocketEvent.TableChange, { id, table: null })
50
54
  }
51
55
  }
@@ -3,7 +3,7 @@ import http from "http"
3
3
  import Koa from "koa"
4
4
  import Cookies from "cookies"
5
5
  import { userAgent } from "koa-useragent"
6
- import { auth, redis } from "@budibase/backend-core"
6
+ import { auth, Header, redis } from "@budibase/backend-core"
7
7
  import currentApp from "../middleware/currentapp"
8
8
  import { createAdapter } from "@socket.io/redis-adapter"
9
9
  import { Socket } from "socket.io"
@@ -271,4 +271,13 @@ export class BaseSocket {
271
271
  emit(event: string, payload: any) {
272
272
  this.io.sockets.emit(event, payload)
273
273
  }
274
+
275
+ // Emit an event to everyone in a room, including metadata of whom
276
+ // the originator of the request was
277
+ emitToRoom(ctx: any, room: string, event: string, payload: any) {
278
+ this.io.in(room).emit(event, {
279
+ ...payload,
280
+ apiSessionId: ctx.headers?.[Header.SESSION_ID],
281
+ })
282
+ }
274
283
  }