@budibase/server 2.3.18-alpha.2 → 2.3.18-alpha.21
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.bbe4c16b.js → index.baf0ac34.js} +430 -417
- package/builder/assets/index.dc0472d8.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/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/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
|
Binary file
|
package/builder/index.html
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap"
|
|
11
11
|
rel="stylesheet"
|
|
12
12
|
/>
|
|
13
|
-
<script type="module" crossorigin src="/builder/assets/index.
|
|
14
|
-
<link rel="stylesheet" href="/builder/assets/index.
|
|
13
|
+
<script type="module" crossorigin src="/builder/assets/index.baf0ac34.js"></script>
|
|
14
|
+
<link rel="stylesheet" href="/builder/assets/index.dc0472d8.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body id="app">
|
|
17
17
|
|
|
@@ -85,9 +85,13 @@ function create(ctx) {
|
|
|
85
85
|
automation.appId = ctx.appId;
|
|
86
86
|
// call through to update if already exists
|
|
87
87
|
if (automation._id && automation._rev) {
|
|
88
|
-
|
|
88
|
+
yield update(ctx);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Respect existing IDs if recreating a deleted automation
|
|
92
|
+
if (!automation._id) {
|
|
93
|
+
automation._id = (0, utils_1.generateAutomationID)();
|
|
89
94
|
}
|
|
90
|
-
automation._id = (0, utils_1.generateAutomationID)();
|
|
91
95
|
automation.type = "automation";
|
|
92
96
|
automation = cleanAutomationInputs(automation);
|
|
93
97
|
automation = yield (0, utils_2.checkForWebhooks)({
|
|
@@ -137,6 +141,11 @@ function update(ctx) {
|
|
|
137
141
|
const db = backend_core_1.context.getAppDB();
|
|
138
142
|
let automation = ctx.request.body;
|
|
139
143
|
automation.appId = ctx.appId;
|
|
144
|
+
// Call through to create if it doesn't exist
|
|
145
|
+
if (!automation._id || !automation._rev) {
|
|
146
|
+
yield create(ctx);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
140
149
|
const oldAutomation = yield db.get(automation._id);
|
|
141
150
|
automation = cleanAutomationInputs(automation);
|
|
142
151
|
automation = yield (0, utils_2.checkForWebhooks)({
|
|
@@ -71,7 +71,7 @@ function exportApps(ctx) {
|
|
|
71
71
|
exports.exportApps = exportApps;
|
|
72
72
|
function checkHasBeenImported() {
|
|
73
73
|
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
-
if (!environment_1.default.SELF_HOSTED
|
|
74
|
+
if (!environment_1.default.SELF_HOSTED) {
|
|
75
75
|
return true;
|
|
76
76
|
}
|
|
77
77
|
const apps = yield backend_core_1.db.getAllApps({ all: true });
|
|
@@ -88,7 +88,7 @@ function hasBeenImported(ctx) {
|
|
|
88
88
|
exports.hasBeenImported = hasBeenImported;
|
|
89
89
|
function importApps(ctx) {
|
|
90
90
|
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
-
if (!environment_1.default.SELF_HOSTED
|
|
91
|
+
if (!environment_1.default.SELF_HOSTED) {
|
|
92
92
|
ctx.throw(400, "Importing only allowed in self hosted environments.");
|
|
93
93
|
}
|
|
94
94
|
const beenImported = yield checkHasBeenImported();
|
|
@@ -32,7 +32,7 @@ const utils_3 = require("../../../integrations/utils");
|
|
|
32
32
|
const string_templates_1 = require("@budibase/string-templates");
|
|
33
33
|
const fp_1 = require("lodash/fp");
|
|
34
34
|
const rowProcessor_1 = require("../../../utilities/rowProcessor");
|
|
35
|
-
const
|
|
35
|
+
const backend_core_1 = require("@budibase/backend-core");
|
|
36
36
|
const sdk_1 = __importDefault(require("../../../sdk"));
|
|
37
37
|
function buildFilters(id, filters, table) {
|
|
38
38
|
const primary = table.primary;
|
|
@@ -43,7 +43,7 @@ function buildFilters(id, filters, table) {
|
|
|
43
43
|
let prefix = 1;
|
|
44
44
|
for (let operator of Object.values(filters)) {
|
|
45
45
|
for (let field of Object.keys(operator || {})) {
|
|
46
|
-
if (
|
|
46
|
+
if (backend_core_1.db.removeKeyNumbering(field) === "_id") {
|
|
47
47
|
if (primary) {
|
|
48
48
|
const parts = (0, utils_1.breakRowIdField)(operator[field]);
|
|
49
49
|
for (let field of primary) {
|
|
@@ -119,7 +119,7 @@ function cleanupConfig(config, table) {
|
|
|
119
119
|
}
|
|
120
120
|
return config;
|
|
121
121
|
}
|
|
122
|
-
function generateIdForRow(row, table) {
|
|
122
|
+
function generateIdForRow(row, table, isLinked = false) {
|
|
123
123
|
const primary = table.primary;
|
|
124
124
|
if (!row || !primary) {
|
|
125
125
|
return "";
|
|
@@ -127,8 +127,12 @@ function generateIdForRow(row, table) {
|
|
|
127
127
|
// build id array
|
|
128
128
|
let idParts = [];
|
|
129
129
|
for (let field of primary) {
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
let fieldValue = extractFieldValue({
|
|
131
|
+
row,
|
|
132
|
+
tableName: table.name,
|
|
133
|
+
fieldName: field,
|
|
134
|
+
isLinked,
|
|
135
|
+
});
|
|
132
136
|
if (fieldValue) {
|
|
133
137
|
idParts.push(fieldValue);
|
|
134
138
|
}
|
|
@@ -149,18 +153,31 @@ function getEndpoint(tableId, operation) {
|
|
|
149
153
|
operation,
|
|
150
154
|
};
|
|
151
155
|
}
|
|
152
|
-
|
|
156
|
+
// need to handle table name + field or just field, depending on if relationships used
|
|
157
|
+
function extractFieldValue({ row, tableName, fieldName, isLinked, }) {
|
|
158
|
+
let value = row[`${tableName}.${fieldName}`];
|
|
159
|
+
if (value == null && !isLinked) {
|
|
160
|
+
value = row[fieldName];
|
|
161
|
+
}
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
function basicProcessing({ row, table, isLinked, }) {
|
|
153
165
|
const thisRow = {};
|
|
154
166
|
// filter the row down to what is actually the row (not joined)
|
|
155
|
-
for (let
|
|
156
|
-
const
|
|
157
|
-
const value =
|
|
167
|
+
for (let field of Object.values(table.schema)) {
|
|
168
|
+
const fieldName = field.name;
|
|
169
|
+
const value = extractFieldValue({
|
|
170
|
+
row,
|
|
171
|
+
tableName: table.name,
|
|
172
|
+
fieldName,
|
|
173
|
+
isLinked,
|
|
174
|
+
});
|
|
158
175
|
// all responses include "select col as table.col" so that overlaps are handled
|
|
159
176
|
if (value != null) {
|
|
160
177
|
thisRow[fieldName] = value;
|
|
161
178
|
}
|
|
162
179
|
}
|
|
163
|
-
thisRow._id = generateIdForRow(row, table);
|
|
180
|
+
thisRow._id = generateIdForRow(row, table, isLinked);
|
|
164
181
|
thisRow.tableId = table._id;
|
|
165
182
|
thisRow._rev = "rev";
|
|
166
183
|
return (0, rowProcessor_1.processFormulas)(table, thisRow);
|
|
@@ -254,7 +271,7 @@ class ExternalRequest {
|
|
|
254
271
|
// we're not inserting a doc, will be a bunch of update calls
|
|
255
272
|
const otherKey = field.throughFrom || linkTablePrimary;
|
|
256
273
|
const thisKey = field.throughTo || tablePrimary;
|
|
257
|
-
row[key].
|
|
274
|
+
row[key].forEach((relationship) => {
|
|
258
275
|
manyRelationships.push({
|
|
259
276
|
tableId: field.through || field.tableId,
|
|
260
277
|
isUpdate: false,
|
|
@@ -270,7 +287,7 @@ class ExternalRequest {
|
|
|
270
287
|
const thisKey = "id";
|
|
271
288
|
// @ts-ignore
|
|
272
289
|
const otherKey = field.fieldName;
|
|
273
|
-
row[key].
|
|
290
|
+
row[key].forEach((relationship) => {
|
|
274
291
|
manyRelationships.push({
|
|
275
292
|
tableId: field.tableId,
|
|
276
293
|
isUpdate: true,
|
|
@@ -328,7 +345,7 @@ class ExternalRequest {
|
|
|
328
345
|
((_a = row[fromColumn]) === null || _a === void 0 ? void 0 : _a.toString()) !== ((_b = row[toColumn]) === null || _b === void 0 ? void 0 : _b.toString())) {
|
|
329
346
|
continue;
|
|
330
347
|
}
|
|
331
|
-
let linked = basicProcessing(row, linkedTable);
|
|
348
|
+
let linked = basicProcessing({ row, table: linkedTable, isLinked: true });
|
|
332
349
|
if (!linked._id) {
|
|
333
350
|
continue;
|
|
334
351
|
}
|
|
@@ -362,7 +379,7 @@ class ExternalRequest {
|
|
|
362
379
|
finalRows = this.updateRelationshipColumns(table, row, finalRows, relationships);
|
|
363
380
|
continue;
|
|
364
381
|
}
|
|
365
|
-
const thisRow = fixArrayTypes(basicProcessing(row, table), table);
|
|
382
|
+
const thisRow = fixArrayTypes(basicProcessing({ row, table, isLinked: false }), table);
|
|
366
383
|
if (thisRow._id == null) {
|
|
367
384
|
throw "Unable to generate row ID for SQL rows";
|
|
368
385
|
}
|
|
@@ -486,16 +503,25 @@ class ExternalRequest {
|
|
|
486
503
|
const { key, tableId, isUpdate, id } = relationship, rest = __rest(relationship, ["key", "tableId", "isUpdate", "id"]);
|
|
487
504
|
const body = (0, string_templates_1.processObjectSync)(rest, row, {});
|
|
488
505
|
const linkTable = this.getTable(tableId);
|
|
489
|
-
|
|
490
|
-
const linkPrimary =
|
|
506
|
+
const relationshipPrimary = (linkTable === null || linkTable === void 0 ? void 0 : linkTable.primary) || [];
|
|
507
|
+
const linkPrimary = relationshipPrimary[0];
|
|
491
508
|
if (!linkTable || !linkPrimary) {
|
|
492
509
|
return;
|
|
493
510
|
}
|
|
511
|
+
const linkSecondary = relationshipPrimary[1];
|
|
494
512
|
const rows = ((_a = related[key]) === null || _a === void 0 ? void 0 : _a.rows) || [];
|
|
495
|
-
|
|
496
|
-
row[linkPrimary] ===
|
|
513
|
+
function relationshipMatchPredicate({ row, linkPrimary, linkSecondary, }) {
|
|
514
|
+
const matchesPrimaryLink = row[linkPrimary] === relationship.id ||
|
|
515
|
+
row[linkPrimary] === (body === null || body === void 0 ? void 0 : body[linkPrimary]);
|
|
516
|
+
if (!matchesPrimaryLink || !linkSecondary) {
|
|
517
|
+
return matchesPrimaryLink;
|
|
518
|
+
}
|
|
519
|
+
const matchesSecondayLink = row[linkSecondary] === (body === null || body === void 0 ? void 0 : body[linkSecondary]);
|
|
520
|
+
return matchesPrimaryLink && matchesSecondayLink;
|
|
521
|
+
}
|
|
522
|
+
const existingRelationship = rows.find((row) => relationshipMatchPredicate({ row, linkPrimary, linkSecondary }));
|
|
497
523
|
const operation = isUpdate ? types_1.Operation.UPDATE : types_1.Operation.CREATE;
|
|
498
|
-
if (!
|
|
524
|
+
if (!existingRelationship) {
|
|
499
525
|
promises.push((0, utils_2.getDatasourceAndQuery)({
|
|
500
526
|
endpoint: getEndpoint(tableId, operation),
|
|
501
527
|
// if we're doing many relationships then we're writing, only one response
|
|
@@ -505,7 +531,7 @@ class ExternalRequest {
|
|
|
505
531
|
}
|
|
506
532
|
else {
|
|
507
533
|
// remove the relationship from cache so it isn't adjusted again
|
|
508
|
-
rows.splice(rows.indexOf(
|
|
534
|
+
rows.splice(rows.indexOf(existingRelationship), 1);
|
|
509
535
|
}
|
|
510
536
|
}
|
|
511
537
|
// finally cleanup anything that needs to be removed
|
|
@@ -540,7 +566,7 @@ class ExternalRequest {
|
|
|
540
566
|
* Creating the specific list of fields that we desire, and excluding the ones that are no use to us
|
|
541
567
|
* is more performant and has the added benefit of protecting against this scenario.
|
|
542
568
|
*/
|
|
543
|
-
buildFields(table, includeRelations
|
|
569
|
+
buildFields(table, includeRelations) {
|
|
544
570
|
function extractRealFields(table, existing = []) {
|
|
545
571
|
return Object.entries(table.schema)
|
|
546
572
|
.filter(column => column[1].type !== constants_1.FieldTypes.LINK &&
|
|
@@ -594,6 +620,7 @@ class ExternalRequest {
|
|
|
594
620
|
}
|
|
595
621
|
filters = buildFilters(id, filters || {}, table);
|
|
596
622
|
const relationships = this.buildRelationships(table);
|
|
623
|
+
const includeSqlRelationships = config.includeSqlRelationships === types_1.IncludeRelationship.INCLUDE;
|
|
597
624
|
// clean up row on ingress using schema
|
|
598
625
|
const processed = this.inputProcessing(row, table);
|
|
599
626
|
row = processed.row;
|
|
@@ -609,9 +636,7 @@ class ExternalRequest {
|
|
|
609
636
|
},
|
|
610
637
|
resource: {
|
|
611
638
|
// have to specify the fields to avoid column overlap (for SQL)
|
|
612
|
-
fields: isSql
|
|
613
|
-
? this.buildFields(table, config.includeSqlRelationships)
|
|
614
|
-
: [],
|
|
639
|
+
fields: isSql ? this.buildFields(table, includeSqlRelationships) : [],
|
|
615
640
|
},
|
|
616
641
|
filters,
|
|
617
642
|
sort,
|
|
@@ -86,7 +86,7 @@ function patch(ctx) {
|
|
|
86
86
|
return handleRequest(types_1.Operation.UPDATE, tableId, {
|
|
87
87
|
id: (0, utils_1.breakRowIdField)(id),
|
|
88
88
|
row: inputs,
|
|
89
|
-
includeSqlRelationships: types_1.IncludeRelationship.
|
|
89
|
+
includeSqlRelationships: types_1.IncludeRelationship.INCLUDE,
|
|
90
90
|
});
|
|
91
91
|
});
|
|
92
92
|
}
|