@budibase/server 2.3.18-alpha.3 → 2.3.18-alpha.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.
- package/__mocks__/node-fetch.ts +3 -0
- package/builder/assets/blankScreenPreview.72634dd1.png +0 -0
- package/builder/assets/{index.9f78787d.js → index.11e16372.js} +429 -414
- package/builder/assets/index.b24b9dea.css +6 -0
- package/builder/assets/listScreenPreview.599c0aae.png +0 -0
- package/builder/index.html +2 -2
- package/dist/api/controllers/automation.js +11 -2
- package/dist/api/controllers/cloud.js +2 -2
- package/dist/api/controllers/row/ExternalRequest.js +49 -24
- package/dist/api/controllers/row/external.js +1 -1
- package/dist/api/controllers/row/internalSearch.js +6 -450
- package/dist/api/controllers/row/utils.js +1 -3
- package/dist/api/routes/automation.js +1 -1
- package/dist/api/routes/public/applications.js +7 -7
- package/dist/api/routes/public/queries.js +2 -2
- package/dist/api/routes/public/rows.js +5 -5
- package/dist/api/routes/public/tables.js +5 -5
- package/dist/api/routes/public/users.js +5 -5
- package/dist/app.js +2 -0
- package/dist/db/index.js +25 -2
- package/dist/db/utils.js +2 -5
- package/dist/db/views/staticViews.js +2 -1
- package/dist/integrations/base/sql.js +4 -8
- package/dist/integrations/googlesheets.js +17 -20
- package/dist/middleware/authorized.js +5 -3
- package/dist/middleware/builder.js +6 -3
- package/dist/migrations/functions/backfill/global/configs.js +10 -4
- package/dist/migrations/tests/helpers.js +1 -1
- package/dist/migrations/tests/structures.js +1 -1
- package/dist/package.json +9 -8
- package/dist/sdk/app/backups/constants.js +2 -1
- package/dist/sdk/app/backups/exports.js +12 -5
- package/dist/sdk/app/rows/attachments.js +1 -1
- package/dist/startup.js +3 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/jest.config.ts +1 -0
- package/package.json +10 -9
- package/scripts/test.sh +12 -0
- package/specs/{generate.js → generate.ts} +7 -9
- package/specs/openapi.json +24 -24
- package/specs/openapi.yaml +24 -24
- package/specs/{parameters.js → parameters.ts} +6 -6
- package/specs/resources/{application.js → application.ts} +4 -4
- package/specs/resources/{index.js → index.ts} +8 -8
- package/specs/resources/{misc.js → misc.ts} +3 -3
- package/specs/resources/{query.js → query.ts} +4 -4
- package/specs/resources/{row.js → row.ts} +3 -4
- package/specs/resources/{table.js → table.ts} +5 -5
- package/specs/resources/{user.js → user.ts} +3 -3
- package/specs/resources/utils/Resource.ts +39 -0
- package/specs/resources/utils/{index.js → index.ts} +1 -1
- package/specs/{security.js → security.ts} +1 -1
- package/src/api/controllers/automation.ts +13 -2
- package/src/api/controllers/cloud.ts +2 -2
- package/src/api/controllers/row/ExternalRequest.ts +95 -28
- package/src/api/controllers/row/external.ts +1 -1
- package/src/api/controllers/row/internalSearch.ts +11 -524
- package/src/api/controllers/row/utils.ts +1 -2
- package/src/api/routes/automation.ts +1 -1
- package/src/api/routes/public/applications.ts +7 -7
- package/src/api/routes/public/queries.ts +2 -2
- package/src/api/routes/public/rows.ts +5 -5
- package/src/api/routes/public/tables.ts +5 -5
- package/src/api/routes/public/tests/{compare.spec.js → compare.spec.ts} +44 -25
- package/src/api/routes/public/users.ts +5 -5
- package/src/api/routes/tests/{cloud.seq.spec.ts → cloud.spec.ts} +13 -20
- package/src/api/routes/tests/utilities/TestFunctions.ts +1 -2
- package/src/app.ts +2 -0
- package/src/db/index.ts +2 -2
- package/src/db/utils.ts +0 -4
- package/src/db/views/staticViews.ts +3 -3
- package/src/definitions/openapi.ts +449 -63
- package/src/integration-test/postgres.spec.ts +351 -81
- package/src/integrations/base/sql.ts +4 -8
- package/src/integrations/googlesheets.ts +21 -22
- package/src/integrations/tests/googlesheets.spec.ts +122 -0
- package/src/middleware/authorized.ts +6 -4
- package/src/middleware/builder.ts +8 -3
- package/src/migrations/functions/backfill/global/configs.ts +15 -9
- package/src/migrations/functions/tests/userEmailViewCasing.spec.js +3 -4
- package/src/migrations/tests/helpers.ts +2 -2
- package/src/migrations/tests/structures.ts +1 -0
- package/src/sdk/app/backups/constants.ts +1 -0
- package/src/sdk/app/backups/exports.ts +24 -8
- package/src/sdk/app/rows/attachments.ts +1 -1
- package/src/startup.ts +4 -1
- package/src/tests/jestEnv.ts +1 -0
- package/src/tests/utilities/TestConfiguration.ts +42 -30
- package/src/tests/utilities/structures.ts +0 -2
- package/builder/assets/index.7e76c039.css +0 -6
- package/dist/integrations/base/utils.js +0 -16
- package/specs/resources/utils/Resource.js +0 -26
- package/src/integrations/base/utils.ts +0 -12
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { object } from "./utils"
|
|
2
|
+
import Resource from "./utils/Resource"
|
|
3
3
|
|
|
4
4
|
const baseRow = {
|
|
5
5
|
_id: "ro_ta_5b1649e42a5b41dea4ef7742a36a7a70_e6dc7e38cf1343b2b56760265201cda4",
|
|
@@ -56,7 +56,6 @@ const rowSchema = {
|
|
|
56
56
|
const rowOutputSchema = {
|
|
57
57
|
...rowSchema,
|
|
58
58
|
properties: {
|
|
59
|
-
...rowSchema.properties,
|
|
60
59
|
_id: {
|
|
61
60
|
description: "The ID of the row.",
|
|
62
61
|
type: "string",
|
|
@@ -93,7 +92,7 @@ const searchOutputSchema = {
|
|
|
93
92
|
},
|
|
94
93
|
}
|
|
95
94
|
|
|
96
|
-
|
|
95
|
+
export default new Resource()
|
|
97
96
|
.setExamples({
|
|
98
97
|
inputRow: {
|
|
99
98
|
value: inputRow,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import {
|
|
2
2
|
FieldTypes,
|
|
3
3
|
RelationshipTypes,
|
|
4
4
|
FormulaTypes,
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
} from "../../src/constants"
|
|
6
|
+
import { object } from "./utils"
|
|
7
|
+
import Resource from "./utils/Resource"
|
|
8
8
|
|
|
9
9
|
const table = {
|
|
10
10
|
_id: "ta_5b1649e42a5b41dea4ef7742a36a7a70",
|
|
@@ -170,7 +170,7 @@ const tableOutputSchema = {
|
|
|
170
170
|
required: [...tableSchema.required, "_id"],
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
|
|
173
|
+
export default new Resource()
|
|
174
174
|
.setExamples({
|
|
175
175
|
table: {
|
|
176
176
|
value: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { object } from "./utils"
|
|
2
|
+
import Resource from "./utils/Resource"
|
|
3
3
|
|
|
4
4
|
const user = {
|
|
5
5
|
_id: "us_693a73206518477283a8d5ae31103252",
|
|
@@ -105,7 +105,7 @@ const userOutputSchema = {
|
|
|
105
105
|
required: [...userSchema.required, "_id"],
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
export default new Resource()
|
|
109
109
|
.setExamples({
|
|
110
110
|
user: {
|
|
111
111
|
value: {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
type Example = {
|
|
2
|
+
[key: string]: {
|
|
3
|
+
[key: string]: any
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type Schema = {
|
|
8
|
+
[key: string]: {
|
|
9
|
+
[key: string]: any
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default class Resource {
|
|
14
|
+
examples: Example
|
|
15
|
+
schemas: Schema
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
this.examples = {}
|
|
19
|
+
this.schemas = {}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
setExamples(examples: Example) {
|
|
23
|
+
this.examples = examples
|
|
24
|
+
return this
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
setSchemas(schemas: Schema) {
|
|
28
|
+
this.schemas = schemas
|
|
29
|
+
return this
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getExamples() {
|
|
33
|
+
return this.examples
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getSchemas() {
|
|
37
|
+
return this.schemas
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -65,10 +65,14 @@ export async function create(ctx: BBContext) {
|
|
|
65
65
|
|
|
66
66
|
// call through to update if already exists
|
|
67
67
|
if (automation._id && automation._rev) {
|
|
68
|
-
|
|
68
|
+
await update(ctx)
|
|
69
|
+
return
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
|
|
72
|
+
// Respect existing IDs if recreating a deleted automation
|
|
73
|
+
if (!automation._id) {
|
|
74
|
+
automation._id = generateAutomationID()
|
|
75
|
+
}
|
|
72
76
|
|
|
73
77
|
automation.type = "automation"
|
|
74
78
|
automation = cleanAutomationInputs(automation)
|
|
@@ -126,6 +130,13 @@ export async function update(ctx: BBContext) {
|
|
|
126
130
|
const db = context.getAppDB()
|
|
127
131
|
let automation = ctx.request.body
|
|
128
132
|
automation.appId = ctx.appId
|
|
133
|
+
|
|
134
|
+
// Call through to create if it doesn't exist
|
|
135
|
+
if (!automation._id || !automation._rev) {
|
|
136
|
+
await create(ctx)
|
|
137
|
+
return
|
|
138
|
+
}
|
|
139
|
+
|
|
129
140
|
const oldAutomation = await db.get(automation._id)
|
|
130
141
|
automation = cleanAutomationInputs(automation)
|
|
131
142
|
automation = await checkForWebhooks({
|
|
@@ -58,7 +58,7 @@ export async function exportApps(ctx: Ctx) {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
async function checkHasBeenImported() {
|
|
61
|
-
if (!env.SELF_HOSTED
|
|
61
|
+
if (!env.SELF_HOSTED) {
|
|
62
62
|
return true
|
|
63
63
|
}
|
|
64
64
|
const apps = await dbCore.getAllApps({ all: true })
|
|
@@ -72,7 +72,7 @@ export async function hasBeenImported(ctx: Ctx) {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export async function importApps(ctx: Ctx) {
|
|
75
|
-
if (!env.SELF_HOSTED
|
|
75
|
+
if (!env.SELF_HOSTED) {
|
|
76
76
|
ctx.throw(400, "Importing only allowed in self hosted environments.")
|
|
77
77
|
}
|
|
78
78
|
const beenImported = await checkHasBeenImported()
|
|
@@ -24,8 +24,7 @@ import { breakExternalTableId, isSQL } from "../../../integrations/utils"
|
|
|
24
24
|
import { processObjectSync } from "@budibase/string-templates"
|
|
25
25
|
import { cloneDeep } from "lodash/fp"
|
|
26
26
|
import { processFormulas, processDates } from "../../../utilities/rowProcessor"
|
|
27
|
-
import {
|
|
28
|
-
import { removeKeyNumbering } from "./utils"
|
|
27
|
+
import { db as dbCore } from "@budibase/backend-core"
|
|
29
28
|
import sdk from "../../../sdk"
|
|
30
29
|
|
|
31
30
|
export interface ManyRelationship {
|
|
@@ -61,7 +60,7 @@ function buildFilters(
|
|
|
61
60
|
let prefix = 1
|
|
62
61
|
for (let operator of Object.values(filters)) {
|
|
63
62
|
for (let field of Object.keys(operator || {})) {
|
|
64
|
-
if (removeKeyNumbering(field) === "_id") {
|
|
63
|
+
if (dbCore.removeKeyNumbering(field) === "_id") {
|
|
65
64
|
if (primary) {
|
|
66
65
|
const parts = breakRowIdField(operator[field])
|
|
67
66
|
for (let field of primary) {
|
|
@@ -142,7 +141,11 @@ function cleanupConfig(config: RunConfig, table: Table): RunConfig {
|
|
|
142
141
|
return config
|
|
143
142
|
}
|
|
144
143
|
|
|
145
|
-
function generateIdForRow(
|
|
144
|
+
function generateIdForRow(
|
|
145
|
+
row: Row | undefined,
|
|
146
|
+
table: Table,
|
|
147
|
+
isLinked: boolean = false
|
|
148
|
+
): string {
|
|
146
149
|
const primary = table.primary
|
|
147
150
|
if (!row || !primary) {
|
|
148
151
|
return ""
|
|
@@ -150,8 +153,12 @@ function generateIdForRow(row: Row | undefined, table: Table): string {
|
|
|
150
153
|
// build id array
|
|
151
154
|
let idParts = []
|
|
152
155
|
for (let field of primary) {
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
let fieldValue = extractFieldValue({
|
|
157
|
+
row,
|
|
158
|
+
tableName: table.name,
|
|
159
|
+
fieldName: field,
|
|
160
|
+
isLinked,
|
|
161
|
+
})
|
|
155
162
|
if (fieldValue) {
|
|
156
163
|
idParts.push(fieldValue)
|
|
157
164
|
}
|
|
@@ -174,18 +181,52 @@ function getEndpoint(tableId: string | undefined, operation: string) {
|
|
|
174
181
|
}
|
|
175
182
|
}
|
|
176
183
|
|
|
177
|
-
|
|
184
|
+
// need to handle table name + field or just field, depending on if relationships used
|
|
185
|
+
function extractFieldValue({
|
|
186
|
+
row,
|
|
187
|
+
tableName,
|
|
188
|
+
fieldName,
|
|
189
|
+
isLinked,
|
|
190
|
+
}: {
|
|
191
|
+
row: Row
|
|
192
|
+
tableName: string
|
|
193
|
+
fieldName: string
|
|
194
|
+
isLinked: boolean
|
|
195
|
+
}) {
|
|
196
|
+
let value = row[`${tableName}.${fieldName}`]
|
|
197
|
+
if (value == null && !isLinked) {
|
|
198
|
+
value = row[fieldName]
|
|
199
|
+
}
|
|
200
|
+
return value
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function basicProcessing({
|
|
204
|
+
row,
|
|
205
|
+
table,
|
|
206
|
+
isLinked,
|
|
207
|
+
}: {
|
|
208
|
+
row: Row
|
|
209
|
+
table: Table
|
|
210
|
+
isLinked: boolean
|
|
211
|
+
}): Row {
|
|
178
212
|
const thisRow: Row = {}
|
|
179
213
|
// filter the row down to what is actually the row (not joined)
|
|
180
|
-
for (let
|
|
181
|
-
const
|
|
182
|
-
|
|
214
|
+
for (let field of Object.values(table.schema)) {
|
|
215
|
+
const fieldName = field.name
|
|
216
|
+
|
|
217
|
+
const value = extractFieldValue({
|
|
218
|
+
row,
|
|
219
|
+
tableName: table.name,
|
|
220
|
+
fieldName,
|
|
221
|
+
isLinked,
|
|
222
|
+
})
|
|
223
|
+
|
|
183
224
|
// all responses include "select col as table.col" so that overlaps are handled
|
|
184
225
|
if (value != null) {
|
|
185
226
|
thisRow[fieldName] = value
|
|
186
227
|
}
|
|
187
228
|
}
|
|
188
|
-
thisRow._id = generateIdForRow(row, table)
|
|
229
|
+
thisRow._id = generateIdForRow(row, table, isLinked)
|
|
189
230
|
thisRow.tableId = table._id
|
|
190
231
|
thisRow._rev = "rev"
|
|
191
232
|
return processFormulas(table, thisRow)
|
|
@@ -293,7 +334,7 @@ export class ExternalRequest {
|
|
|
293
334
|
// we're not inserting a doc, will be a bunch of update calls
|
|
294
335
|
const otherKey: string = field.throughFrom || linkTablePrimary
|
|
295
336
|
const thisKey: string = field.throughTo || tablePrimary
|
|
296
|
-
row[key].
|
|
337
|
+
row[key].forEach((relationship: any) => {
|
|
297
338
|
manyRelationships.push({
|
|
298
339
|
tableId: field.through || field.tableId,
|
|
299
340
|
isUpdate: false,
|
|
@@ -309,7 +350,7 @@ export class ExternalRequest {
|
|
|
309
350
|
const thisKey: string = "id"
|
|
310
351
|
// @ts-ignore
|
|
311
352
|
const otherKey: string = field.fieldName
|
|
312
|
-
row[key].
|
|
353
|
+
row[key].forEach((relationship: any) => {
|
|
313
354
|
manyRelationships.push({
|
|
314
355
|
tableId: field.tableId,
|
|
315
356
|
isUpdate: true,
|
|
@@ -379,7 +420,8 @@ export class ExternalRequest {
|
|
|
379
420
|
) {
|
|
380
421
|
continue
|
|
381
422
|
}
|
|
382
|
-
|
|
423
|
+
|
|
424
|
+
let linked = basicProcessing({ row, table: linkedTable, isLinked: true })
|
|
383
425
|
if (!linked._id) {
|
|
384
426
|
continue
|
|
385
427
|
}
|
|
@@ -427,7 +469,10 @@ export class ExternalRequest {
|
|
|
427
469
|
)
|
|
428
470
|
continue
|
|
429
471
|
}
|
|
430
|
-
const thisRow = fixArrayTypes(
|
|
472
|
+
const thisRow = fixArrayTypes(
|
|
473
|
+
basicProcessing({ row, table, isLinked: false }),
|
|
474
|
+
table
|
|
475
|
+
)
|
|
431
476
|
if (thisRow._id == null) {
|
|
432
477
|
throw "Unable to generate row ID for SQL rows"
|
|
433
478
|
}
|
|
@@ -567,19 +612,41 @@ export class ExternalRequest {
|
|
|
567
612
|
const { key, tableId, isUpdate, id, ...rest } = relationship
|
|
568
613
|
const body: { [key: string]: any } = processObjectSync(rest, row, {})
|
|
569
614
|
const linkTable = this.getTable(tableId)
|
|
570
|
-
|
|
571
|
-
const linkPrimary =
|
|
615
|
+
const relationshipPrimary = linkTable?.primary || []
|
|
616
|
+
const linkPrimary = relationshipPrimary[0]
|
|
572
617
|
if (!linkTable || !linkPrimary) {
|
|
573
618
|
return
|
|
574
619
|
}
|
|
620
|
+
|
|
621
|
+
const linkSecondary = relationshipPrimary[1]
|
|
622
|
+
|
|
575
623
|
const rows = related[key]?.rows || []
|
|
576
|
-
|
|
577
|
-
|
|
624
|
+
|
|
625
|
+
function relationshipMatchPredicate({
|
|
626
|
+
row,
|
|
627
|
+
linkPrimary,
|
|
628
|
+
linkSecondary,
|
|
629
|
+
}: {
|
|
630
|
+
row: { [key: string]: any }
|
|
631
|
+
linkPrimary: string
|
|
632
|
+
linkSecondary?: string
|
|
633
|
+
}) {
|
|
634
|
+
const matchesPrimaryLink =
|
|
578
635
|
row[linkPrimary] === relationship.id ||
|
|
579
636
|
row[linkPrimary] === body?.[linkPrimary]
|
|
637
|
+
if (!matchesPrimaryLink || !linkSecondary) {
|
|
638
|
+
return matchesPrimaryLink
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
const matchesSecondayLink = row[linkSecondary] === body?.[linkSecondary]
|
|
642
|
+
return matchesPrimaryLink && matchesSecondayLink
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
const existingRelationship = rows.find((row: { [key: string]: any }) =>
|
|
646
|
+
relationshipMatchPredicate({ row, linkPrimary, linkSecondary })
|
|
580
647
|
)
|
|
581
648
|
const operation = isUpdate ? Operation.UPDATE : Operation.CREATE
|
|
582
|
-
if (!
|
|
649
|
+
if (!existingRelationship) {
|
|
583
650
|
promises.push(
|
|
584
651
|
getDatasourceAndQuery({
|
|
585
652
|
endpoint: getEndpoint(tableId, operation),
|
|
@@ -590,7 +657,7 @@ export class ExternalRequest {
|
|
|
590
657
|
)
|
|
591
658
|
} else {
|
|
592
659
|
// remove the relationship from cache so it isn't adjusted again
|
|
593
|
-
rows.splice(rows.indexOf(
|
|
660
|
+
rows.splice(rows.indexOf(existingRelationship), 1)
|
|
594
661
|
}
|
|
595
662
|
}
|
|
596
663
|
// finally cleanup anything that needs to be removed
|
|
@@ -629,10 +696,7 @@ export class ExternalRequest {
|
|
|
629
696
|
* Creating the specific list of fields that we desire, and excluding the ones that are no use to us
|
|
630
697
|
* is more performant and has the added benefit of protecting against this scenario.
|
|
631
698
|
*/
|
|
632
|
-
buildFields(
|
|
633
|
-
table: Table,
|
|
634
|
-
includeRelations: IncludeRelationship = IncludeRelationship.INCLUDE
|
|
635
|
-
) {
|
|
699
|
+
buildFields(table: Table, includeRelations: boolean) {
|
|
636
700
|
function extractRealFields(table: Table, existing: string[] = []) {
|
|
637
701
|
return Object.entries(table.schema)
|
|
638
702
|
.filter(
|
|
@@ -691,6 +755,10 @@ export class ExternalRequest {
|
|
|
691
755
|
}
|
|
692
756
|
filters = buildFilters(id, filters || {}, table)
|
|
693
757
|
const relationships = this.buildRelationships(table)
|
|
758
|
+
|
|
759
|
+
const includeSqlRelationships =
|
|
760
|
+
config.includeSqlRelationships === IncludeRelationship.INCLUDE
|
|
761
|
+
|
|
694
762
|
// clean up row on ingress using schema
|
|
695
763
|
const processed = this.inputProcessing(row, table)
|
|
696
764
|
row = processed.row
|
|
@@ -708,9 +776,7 @@ export class ExternalRequest {
|
|
|
708
776
|
},
|
|
709
777
|
resource: {
|
|
710
778
|
// have to specify the fields to avoid column overlap (for SQL)
|
|
711
|
-
fields: isSql
|
|
712
|
-
? this.buildFields(table, config.includeSqlRelationships)
|
|
713
|
-
: [],
|
|
779
|
+
fields: isSql ? this.buildFields(table, includeSqlRelationships) : [],
|
|
714
780
|
},
|
|
715
781
|
filters,
|
|
716
782
|
sort,
|
|
@@ -725,6 +791,7 @@ export class ExternalRequest {
|
|
|
725
791
|
table,
|
|
726
792
|
},
|
|
727
793
|
}
|
|
794
|
+
|
|
728
795
|
// can't really use response right now
|
|
729
796
|
const response = await getDatasourceAndQuery(json)
|
|
730
797
|
// handle many to many relationships now if we know the ID (could be auto increment)
|
|
@@ -58,7 +58,7 @@ export async function patch(ctx: BBContext) {
|
|
|
58
58
|
return handleRequest(Operation.UPDATE, tableId, {
|
|
59
59
|
id: breakRowIdField(id),
|
|
60
60
|
row: inputs,
|
|
61
|
-
includeSqlRelationships: IncludeRelationship.
|
|
61
|
+
includeSqlRelationships: IncludeRelationship.INCLUDE,
|
|
62
62
|
})
|
|
63
63
|
}
|
|
64
64
|
|