@budibase/server 2.4.40 → 2.4.42-alpha.0
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 +6 -1
- package/builder/assets/index.3cb1022d.css +6 -0
- package/builder/assets/{index.07ed2ead.js → index.4b6c8c0e.js} +384 -383
- package/builder/index.html +7 -7
- package/dist/api/controllers/application.js +28 -24
- package/dist/api/controllers/datasource.js +2 -1
- package/dist/api/controllers/public/metrics.js +113 -0
- package/dist/api/controllers/row/external.js +16 -8
- package/dist/api/controllers/row/index.js +11 -1
- package/dist/api/controllers/row/internal.js +1 -10
- package/dist/api/controllers/row/utils.js +7 -7
- package/dist/api/controllers/static/index.js +84 -24
- package/dist/api/controllers/static/templates/BudibaseApp.svelte +33 -10
- package/dist/api/controllers/table/external.js +16 -12
- package/dist/api/controllers/table/utils.js +15 -1
- package/dist/api/routes/public/index.js +8 -0
- package/dist/api/routes/public/metrics.js +30 -0
- package/dist/app.js +1 -0
- package/dist/constants/index.js +2 -1
- package/dist/integrations/googlesheets.js +125 -59
- package/dist/integrations/redis.js +1 -1
- package/dist/integrations/utils.js +17 -2
- package/dist/package.json +13 -12
- package/dist/sdk/users/utils.js +2 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utilities/global.js +17 -7
- package/jest.config.ts +1 -0
- package/package.json +14 -13
- package/scripts/test.sh +3 -3
- package/specs/openapi.json +39 -0
- package/specs/openapi.yaml +169 -0
- package/specs/resources/application.ts +11 -0
- package/specs/resources/index.ts +2 -0
- package/specs/resources/metrics.ts +81 -0
- package/src/api/controllers/application.ts +20 -21
- package/src/api/controllers/datasource.ts +2 -1
- package/src/api/controllers/public/metrics.ts +251 -0
- package/src/api/controllers/row/external.ts +26 -16
- package/src/api/controllers/row/index.ts +12 -2
- package/src/api/controllers/row/internal.ts +0 -7
- package/src/api/controllers/row/utils.ts +7 -7
- package/src/api/controllers/static/index.ts +69 -26
- package/src/api/controllers/static/templates/BudibaseApp.svelte +33 -10
- package/src/api/controllers/table/external.ts +24 -17
- package/src/api/controllers/table/index.ts +9 -9
- package/src/api/controllers/table/utils.ts +18 -2
- package/src/api/controllers/view/tests/__snapshots__/viewBuilder.spec.js.snap +48 -48
- package/src/api/routes/public/index.ts +10 -1
- package/src/api/routes/public/metrics.ts +28 -0
- package/src/api/routes/public/tests/metrics.spec.js +34 -0
- package/src/api/routes/tests/__snapshots__/datasource.spec.ts.snap +22 -22
- package/src/api/routes/tests/__snapshots__/view.spec.js.snap +5 -5
- package/src/api/routes/tests/appSync.spec.ts +31 -0
- package/src/api/routes/tests/internalSearch.spec.js +8 -7
- package/src/app.ts +2 -1
- package/src/automations/automationUtils.ts +1 -1
- package/src/automations/tests/automation.spec.ts +99 -0
- package/src/constants/index.ts +1 -0
- package/src/definitions/openapi.ts +15 -0
- package/src/integration-test/postgres.spec.ts +46 -52
- package/src/integrations/googlesheets.ts +143 -71
- package/src/integrations/redis.ts +1 -1
- package/src/integrations/tests/googlesheets.spec.ts +13 -13
- package/src/integrations/tests/redis.spec.ts +9 -5
- package/src/integrations/utils.ts +16 -4
- package/src/middleware/currentapp.ts +2 -2
- package/src/sdk/users/utils.ts +4 -1
- package/src/tests/jestEnv.ts +1 -0
- package/src/tests/jestSetup.ts +5 -1
- package/src/tests/utilities/TestConfiguration.ts +13 -0
- package/src/tests/utilities/structures.ts +13 -1
- package/src/utilities/global.ts +21 -9
- package/builder/assets/favicon.e7fc7733.png +0 -0
- package/builder/assets/index.b0e3aca6.css +0 -6
- package/src/automations/tests/automation.spec.js +0 -84
|
@@ -150,16 +150,16 @@ function isRelationshipSetup(column) {
|
|
|
150
150
|
}
|
|
151
151
|
function save(ctx) {
|
|
152
152
|
return __awaiter(this, void 0, void 0, function* () {
|
|
153
|
-
const
|
|
154
|
-
const renamed =
|
|
153
|
+
const inputs = ctx.request.body;
|
|
154
|
+
const renamed = inputs === null || inputs === void 0 ? void 0 : inputs._rename;
|
|
155
155
|
// can't do this right now
|
|
156
|
-
delete
|
|
156
|
+
delete inputs.rows;
|
|
157
157
|
const datasourceId = getDatasourceId(ctx.request.body);
|
|
158
158
|
// table doesn't exist already, note that it is created
|
|
159
|
-
if (!
|
|
160
|
-
|
|
159
|
+
if (!inputs._id) {
|
|
160
|
+
inputs.created = true;
|
|
161
161
|
}
|
|
162
|
-
let tableToSave = Object.assign({ type: "table", _id: (0, utils_1.buildExternalTableId)(datasourceId,
|
|
162
|
+
let tableToSave = Object.assign({ type: "table", _id: (0, utils_1.buildExternalTableId)(datasourceId, inputs.name) }, inputs);
|
|
163
163
|
let oldTable;
|
|
164
164
|
if (ctx.request.body && ctx.request.body._id) {
|
|
165
165
|
oldTable = yield sdk_1.default.tables.getTable(ctx.request.body._id);
|
|
@@ -172,6 +172,8 @@ function save(ctx) {
|
|
|
172
172
|
if (!datasource.entities) {
|
|
173
173
|
datasource.entities = {};
|
|
174
174
|
}
|
|
175
|
+
// GSheets is a specific case - only ever has a static primary key
|
|
176
|
+
tableToSave = (0, utils_2.setStaticSchemas)(datasource, tableToSave);
|
|
175
177
|
const oldTables = cloneDeep(datasource.entities);
|
|
176
178
|
const tables = datasource.entities;
|
|
177
179
|
const extraTablesToUpdate = [];
|
|
@@ -187,7 +189,7 @@ function save(ctx) {
|
|
|
187
189
|
const relatedColumnName = schema.fieldName;
|
|
188
190
|
const relationType = schema.relationshipType;
|
|
189
191
|
if (relationType === types_1.RelationshipTypes.MANY_TO_MANY) {
|
|
190
|
-
const junctionTable = generateManyLinkSchema(datasource, schema,
|
|
192
|
+
const junctionTable = generateManyLinkSchema(datasource, schema, tableToSave, relatedTable);
|
|
191
193
|
if (tables[junctionTable.name]) {
|
|
192
194
|
throw "Junction table already exists, cannot create another relationship.";
|
|
193
195
|
}
|
|
@@ -195,8 +197,10 @@ function save(ctx) {
|
|
|
195
197
|
extraTablesToUpdate.push(junctionTable);
|
|
196
198
|
}
|
|
197
199
|
else {
|
|
198
|
-
const fkTable = relationType === types_1.RelationshipTypes.ONE_TO_MANY
|
|
199
|
-
|
|
200
|
+
const fkTable = relationType === types_1.RelationshipTypes.ONE_TO_MANY
|
|
201
|
+
? tableToSave
|
|
202
|
+
: relatedTable;
|
|
203
|
+
const foreignKey = generateLinkSchema(schema, tableToSave, relatedTable, relationType);
|
|
200
204
|
fkTable.schema[foreignKey] = (0, utils_2.foreignKeyStructure)(foreignKey);
|
|
201
205
|
if (fkTable.constrained == null) {
|
|
202
206
|
fkTable.constrained = [];
|
|
@@ -205,11 +209,11 @@ function save(ctx) {
|
|
|
205
209
|
fkTable.constrained.push(foreignKey);
|
|
206
210
|
}
|
|
207
211
|
// foreign key is in other table, need to save it to external
|
|
208
|
-
if (fkTable._id !==
|
|
212
|
+
if (fkTable._id !== tableToSave._id) {
|
|
209
213
|
extraTablesToUpdate.push(fkTable);
|
|
210
214
|
}
|
|
211
215
|
}
|
|
212
|
-
generateRelatedSchema(schema, relatedTable,
|
|
216
|
+
generateRelatedSchema(schema, relatedTable, tableToSave, relatedColumnName);
|
|
213
217
|
schema.main = true;
|
|
214
218
|
}
|
|
215
219
|
cleanupRelationships(tableToSave, tables, oldTable);
|
|
@@ -264,7 +268,7 @@ function bulkImport(ctx) {
|
|
|
264
268
|
if (!rows || !(0, schema_1.isRows)(rows) || !(0, schema_1.isSchema)(schema)) {
|
|
265
269
|
ctx.throw(400, "Provided data import information is invalid.");
|
|
266
270
|
}
|
|
267
|
-
const parsedRows =
|
|
271
|
+
const parsedRows = (0, schema_1.parse)(rows, schema);
|
|
268
272
|
yield (0, external_1.handleRequest)(types_1.Operation.BULK_CREATE, table._id, {
|
|
269
273
|
rows: parsedRows,
|
|
270
274
|
});
|
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.TableSaveFunctions = exports.hasTypeChanged = exports.areSwitchableTypes = exports.foreignKeyStructure = exports.generateJunctionTableName = exports.generateForeignKey = exports.checkForViewUpdates = exports.checkStaticTables = exports.handleSearchIndexes = exports.handleDataImport = exports.importToRows = exports.makeSureTableUpToDate = exports.checkForColumnUpdates = exports.clearColumns = void 0;
|
|
15
|
+
exports.TableSaveFunctions = exports.setStaticSchemas = exports.hasTypeChanged = exports.areSwitchableTypes = exports.foreignKeyStructure = exports.generateJunctionTableName = exports.generateForeignKey = exports.checkForViewUpdates = exports.checkStaticTables = exports.handleSearchIndexes = exports.handleDataImport = exports.importToRows = exports.makeSureTableUpToDate = exports.checkForColumnUpdates = exports.clearColumns = void 0;
|
|
16
16
|
const schema_1 = require("../../../utilities/schema");
|
|
17
17
|
const utils_1 = require("../../../db/utils");
|
|
18
18
|
const lodash_1 = require("lodash");
|
|
@@ -24,6 +24,7 @@ const viewBuilder_1 = __importDefault(require("../view/viewBuilder"));
|
|
|
24
24
|
const fp_1 = require("lodash/fp");
|
|
25
25
|
const pro_1 = require("@budibase/pro");
|
|
26
26
|
const backend_core_1 = require("@budibase/backend-core");
|
|
27
|
+
const types_1 = require("@budibase/types");
|
|
27
28
|
function clearColumns(table, columnNames) {
|
|
28
29
|
return __awaiter(this, void 0, void 0, function* () {
|
|
29
30
|
const db = backend_core_1.context.getAppDB();
|
|
@@ -356,5 +357,18 @@ function hasTypeChanged(table, oldTable) {
|
|
|
356
357
|
return false;
|
|
357
358
|
}
|
|
358
359
|
exports.hasTypeChanged = hasTypeChanged;
|
|
360
|
+
// used for external tables, some of them will have static schemas that need
|
|
361
|
+
// to be hard set
|
|
362
|
+
function setStaticSchemas(datasource, table) {
|
|
363
|
+
var _a;
|
|
364
|
+
// GSheets is a specific case - only ever has a static primary key
|
|
365
|
+
if (table && datasource.source === types_1.SourceName.GOOGLE_SHEETS) {
|
|
366
|
+
table.primary = [constants_1.GOOGLE_SHEETS_PRIMARY_KEY];
|
|
367
|
+
// if there is an id column, remove it, should never exist in GSheets
|
|
368
|
+
(_a = table.schema) === null || _a === void 0 ? true : delete _a.id;
|
|
369
|
+
}
|
|
370
|
+
return table;
|
|
371
|
+
}
|
|
372
|
+
exports.setStaticSchemas = setStaticSchemas;
|
|
359
373
|
const _TableSaveFunctions = TableSaveFunctions;
|
|
360
374
|
exports.TableSaveFunctions = _TableSaveFunctions;
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.shutdown = void 0;
|
|
7
7
|
const applications_1 = __importDefault(require("./applications"));
|
|
8
|
+
const metrics_1 = __importDefault(require("./metrics"));
|
|
8
9
|
const queries_1 = __importDefault(require("./queries"));
|
|
9
10
|
const tables_1 = __importDefault(require("./tables"));
|
|
10
11
|
const rows_1 = __importDefault(require("./rows"));
|
|
@@ -86,6 +87,12 @@ function addToRouter(endpoints) {
|
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
}
|
|
90
|
+
function applyAdminRoutes(endpoints) {
|
|
91
|
+
addMiddleware(endpoints.read, backend_core_1.middleware.builderOrAdmin);
|
|
92
|
+
addMiddleware(endpoints.write, backend_core_1.middleware.builderOrAdmin);
|
|
93
|
+
addToRouter(endpoints.read);
|
|
94
|
+
addToRouter(endpoints.write);
|
|
95
|
+
}
|
|
89
96
|
function applyRoutes(endpoints, permType, resource, subResource) {
|
|
90
97
|
const paramMiddleware = subResource
|
|
91
98
|
? (0, resourceId_1.paramSubResource)(resource, subResource)
|
|
@@ -107,6 +114,7 @@ function applyRoutes(endpoints, permType, resource, subResource) {
|
|
|
107
114
|
addToRouter(endpoints.read);
|
|
108
115
|
addToRouter(endpoints.write);
|
|
109
116
|
}
|
|
117
|
+
applyAdminRoutes(metrics_1.default);
|
|
110
118
|
applyRoutes(applications_1.default, PermissionType.APP, "appId");
|
|
111
119
|
applyRoutes(tables_1.default, PermissionType.TABLE, "tableId");
|
|
112
120
|
applyRoutes(users_1.default, PermissionType.USER, "userId");
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const metrics_1 = __importDefault(require("../../controllers/public/metrics"));
|
|
7
|
+
const Endpoint_1 = __importDefault(require("./utils/Endpoint"));
|
|
8
|
+
const read = [];
|
|
9
|
+
/**
|
|
10
|
+
* @openapi
|
|
11
|
+
* /metrics:
|
|
12
|
+
* get:
|
|
13
|
+
* operationId: metricsGet
|
|
14
|
+
* summary: Retrieve Budibase tenant metrics
|
|
15
|
+
* description: Output metrics in OpenMetrics format compatible with Prometheus
|
|
16
|
+
* tags:
|
|
17
|
+
* - metrics
|
|
18
|
+
* responses:
|
|
19
|
+
* 200:
|
|
20
|
+
* description: Returns tenant metrics.
|
|
21
|
+
* content:
|
|
22
|
+
* text/plain:
|
|
23
|
+
* schema:
|
|
24
|
+
* type: string
|
|
25
|
+
* examples:
|
|
26
|
+
* metrics:
|
|
27
|
+
* $ref: '#/components/examples/metrics'
|
|
28
|
+
*/
|
|
29
|
+
read.push(new Endpoint_1.default("get", "/metrics", metrics_1.default.fetch));
|
|
30
|
+
exports.default = { read };
|
package/dist/app.js
CHANGED
|
@@ -105,6 +105,7 @@ server.on("close", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
105
105
|
}
|
|
106
106
|
shuttingDown = true;
|
|
107
107
|
console.log("Server Closed");
|
|
108
|
+
backend_core_1.timers.cleanup();
|
|
108
109
|
yield automations.shutdown();
|
|
109
110
|
yield redis.shutdown();
|
|
110
111
|
backend_core_1.events.shutdown();
|
package/dist/constants/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MAX_AUTOMATION_RECURRING_ERRORS = exports.ObjectStoreBuckets = exports.AutomationErrors = exports.BuildSchemaErrors = exports.InvalidColumns = exports.MetadataTypes = exports.BaseQueryVerbs = exports.OBJ_STORE_DIRECTORY = exports.AutoFieldDefaultNames = exports.AutoFieldSubTypes = exports.USERS_TABLE_SCHEMA = exports.SortDirection = exports.DatasourceAuthTypes = exports.DataSourceOperation = exports.AuthTypes = exports.FormulaTypes = exports.SwitchableTypes = exports.CanSwitchTypes = exports.NoEmptyFilterStrings = exports.FilterTypes = exports.RelationshipTypes = exports.FieldTypes = void 0;
|
|
3
|
+
exports.GOOGLE_SHEETS_PRIMARY_KEY = exports.MAX_AUTOMATION_RECURRING_ERRORS = exports.ObjectStoreBuckets = exports.AutomationErrors = exports.BuildSchemaErrors = exports.InvalidColumns = exports.MetadataTypes = exports.BaseQueryVerbs = exports.OBJ_STORE_DIRECTORY = exports.AutoFieldDefaultNames = exports.AutoFieldSubTypes = exports.USERS_TABLE_SCHEMA = exports.SortDirection = exports.DatasourceAuthTypes = exports.DataSourceOperation = exports.AuthTypes = exports.FormulaTypes = exports.SwitchableTypes = exports.CanSwitchTypes = exports.NoEmptyFilterStrings = exports.FilterTypes = exports.RelationshipTypes = exports.FieldTypes = void 0;
|
|
4
4
|
const backend_core_1 = require("@budibase/backend-core");
|
|
5
5
|
var types_1 = require("@budibase/types");
|
|
6
6
|
Object.defineProperty(exports, "FieldTypes", { enumerable: true, get: function () { return types_1.FieldType; } });
|
|
@@ -178,3 +178,4 @@ var AutomationErrors;
|
|
|
178
178
|
// pass through the list from the auth/core lib
|
|
179
179
|
exports.ObjectStoreBuckets = backend_core_1.objectStore.ObjectStoreBuckets;
|
|
180
180
|
exports.MAX_AUTOMATION_RECURRING_ERRORS = 5;
|
|
181
|
+
exports.GOOGLE_SHEETS_PRIMARY_KEY = "rowNumber";
|
|
@@ -15,11 +15,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
const types_1 = require("@budibase/types");
|
|
16
16
|
const google_auth_library_1 = require("google-auth-library");
|
|
17
17
|
const utils_1 = require("./utils");
|
|
18
|
-
const constants_1 = require("../constants");
|
|
19
18
|
const google_spreadsheet_1 = require("google-spreadsheet");
|
|
20
19
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
21
20
|
const backend_core_1 = require("@budibase/backend-core");
|
|
22
21
|
const shared_core_1 = require("@budibase/shared-core");
|
|
22
|
+
const constants_1 = require("../constants");
|
|
23
|
+
const ALLOWED_TYPES = [
|
|
24
|
+
types_1.FieldType.STRING,
|
|
25
|
+
types_1.FieldType.FORMULA,
|
|
26
|
+
types_1.FieldType.NUMBER,
|
|
27
|
+
types_1.FieldType.LONGFORM,
|
|
28
|
+
types_1.FieldType.DATETIME,
|
|
29
|
+
types_1.FieldType.OPTIONS,
|
|
30
|
+
types_1.FieldType.BOOLEAN,
|
|
31
|
+
types_1.FieldType.BARCODEQR,
|
|
32
|
+
];
|
|
23
33
|
const SCHEMA = {
|
|
24
34
|
plus: true,
|
|
25
35
|
auth: {
|
|
@@ -135,6 +145,7 @@ class GoogleSheetsIntegration {
|
|
|
135
145
|
});
|
|
136
146
|
}
|
|
137
147
|
connect() {
|
|
148
|
+
var _a;
|
|
138
149
|
return __awaiter(this, void 0, void 0, function* () {
|
|
139
150
|
try {
|
|
140
151
|
// Initialise oAuth client
|
|
@@ -159,12 +170,36 @@ class GoogleSheetsIntegration {
|
|
|
159
170
|
yield this.client.loadInfo();
|
|
160
171
|
}
|
|
161
172
|
catch (err) {
|
|
173
|
+
// this happens for xlsx imports
|
|
174
|
+
if ((_a = err.message) === null || _a === void 0 ? void 0 : _a.includes("operation is not supported")) {
|
|
175
|
+
err.message =
|
|
176
|
+
"This operation is not supported - XLSX sheets must be converted.";
|
|
177
|
+
}
|
|
162
178
|
console.error("Error connecting to google sheets", err);
|
|
163
179
|
throw err;
|
|
164
180
|
}
|
|
165
181
|
});
|
|
166
182
|
}
|
|
167
|
-
|
|
183
|
+
getTableSchema(title, headerValues, id) {
|
|
184
|
+
// base table
|
|
185
|
+
const table = {
|
|
186
|
+
name: title,
|
|
187
|
+
primary: [constants_1.GOOGLE_SHEETS_PRIMARY_KEY],
|
|
188
|
+
schema: {},
|
|
189
|
+
};
|
|
190
|
+
if (id) {
|
|
191
|
+
table._id = id;
|
|
192
|
+
}
|
|
193
|
+
// build schema from headers
|
|
194
|
+
for (let header of headerValues) {
|
|
195
|
+
table.schema[header] = {
|
|
196
|
+
name: header,
|
|
197
|
+
type: types_1.FieldType.STRING,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return table;
|
|
201
|
+
}
|
|
202
|
+
buildSchema(datasourceId, entities) {
|
|
168
203
|
return __awaiter(this, void 0, void 0, function* () {
|
|
169
204
|
yield this.connect();
|
|
170
205
|
const sheets = this.client.sheetsByIndex;
|
|
@@ -172,56 +207,47 @@ class GoogleSheetsIntegration {
|
|
|
172
207
|
for (let sheet of sheets) {
|
|
173
208
|
// must fetch rows to determine schema
|
|
174
209
|
yield sheet.getRows();
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// build schema from headers
|
|
178
|
-
for (let header of sheet.headerValues) {
|
|
179
|
-
schema[header] = {
|
|
180
|
-
name: header,
|
|
181
|
-
type: constants_1.FieldTypes.STRING,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
// create tables
|
|
185
|
-
tables[sheet.title] = {
|
|
186
|
-
_id: (0, utils_1.buildExternalTableId)(datasourceId, sheet.title),
|
|
187
|
-
name: sheet.title,
|
|
188
|
-
primary: ["rowNumber"],
|
|
189
|
-
schema,
|
|
190
|
-
};
|
|
210
|
+
const id = (0, utils_1.buildExternalTableId)(datasourceId, sheet.title);
|
|
211
|
+
tables[sheet.title] = this.getTableSchema(sheet.title, sheet.headerValues, id);
|
|
191
212
|
}
|
|
192
|
-
|
|
213
|
+
const final = (0, utils_1.finaliseExternalTables)(tables, entities);
|
|
214
|
+
this.tables = final.tables;
|
|
215
|
+
this.schemaErrors = final.errors;
|
|
193
216
|
});
|
|
194
217
|
}
|
|
195
218
|
query(json) {
|
|
219
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
196
220
|
return __awaiter(this, void 0, void 0, function* () {
|
|
197
221
|
const sheet = json.endpoint.entityId;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
222
|
+
switch (json.endpoint.operation) {
|
|
223
|
+
case types_1.Operation.CREATE:
|
|
224
|
+
return this.create({ sheet, row: json.body });
|
|
225
|
+
case types_1.Operation.BULK_CREATE:
|
|
226
|
+
return this.createBulk({ sheet, rows: json.body });
|
|
227
|
+
case types_1.Operation.READ:
|
|
228
|
+
return this.read(Object.assign(Object.assign({}, json), { sheet }));
|
|
229
|
+
case types_1.Operation.UPDATE:
|
|
203
230
|
return this.update({
|
|
204
231
|
// exclude the header row and zero index
|
|
205
232
|
rowIndex: ((_c = (_b = (_a = json.extra) === null || _a === void 0 ? void 0 : _a.idFilter) === null || _b === void 0 ? void 0 : _b.equal) === null || _c === void 0 ? void 0 : _c.rowNumber) - 2,
|
|
206
233
|
sheet,
|
|
207
234
|
row: json.body,
|
|
208
235
|
});
|
|
209
|
-
|
|
210
|
-
[constants_1.DataSourceOperation.DELETE]: () => {
|
|
211
|
-
var _a, _b, _c;
|
|
236
|
+
case types_1.Operation.DELETE:
|
|
212
237
|
return this.delete({
|
|
213
238
|
// exclude the header row and zero index
|
|
214
|
-
rowIndex: ((
|
|
239
|
+
rowIndex: ((_f = (_e = (_d = json.extra) === null || _d === void 0 ? void 0 : _d.idFilter) === null || _e === void 0 ? void 0 : _e.equal) === null || _f === void 0 ? void 0 : _f.rowNumber) - 2,
|
|
215
240
|
sheet,
|
|
216
241
|
});
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
242
|
+
case types_1.Operation.CREATE_TABLE:
|
|
243
|
+
return this.createTable((_g = json === null || json === void 0 ? void 0 : json.table) === null || _g === void 0 ? void 0 : _g.name);
|
|
244
|
+
case types_1.Operation.UPDATE_TABLE:
|
|
245
|
+
return this.updateTable(json.table);
|
|
246
|
+
case types_1.Operation.DELETE_TABLE:
|
|
247
|
+
return this.deleteTable((_h = json === null || json === void 0 ? void 0 : json.table) === null || _h === void 0 ? void 0 : _h.name);
|
|
248
|
+
default:
|
|
249
|
+
throw new Error(`GSheets integration does not support "${json.endpoint.operation}".`);
|
|
250
|
+
}
|
|
225
251
|
});
|
|
226
252
|
}
|
|
227
253
|
buildRowObject(headers, values, rowNumber) {
|
|
@@ -234,9 +260,12 @@ class GoogleSheetsIntegration {
|
|
|
234
260
|
}
|
|
235
261
|
createTable(name) {
|
|
236
262
|
return __awaiter(this, void 0, void 0, function* () {
|
|
263
|
+
if (!name) {
|
|
264
|
+
throw new Error("Must provide name for new sheet.");
|
|
265
|
+
}
|
|
237
266
|
try {
|
|
238
267
|
yield this.connect();
|
|
239
|
-
return yield this.client.addSheet({ title: name, headerValues: [
|
|
268
|
+
return yield this.client.addSheet({ title: name, headerValues: [name] });
|
|
240
269
|
}
|
|
241
270
|
catch (err) {
|
|
242
271
|
console.error("Error creating new table in google sheets", err);
|
|
@@ -246,34 +275,53 @@ class GoogleSheetsIntegration {
|
|
|
246
275
|
}
|
|
247
276
|
updateTable(table) {
|
|
248
277
|
return __awaiter(this, void 0, void 0, function* () {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
headers.push(header);
|
|
261
|
-
}
|
|
278
|
+
yield this.connect();
|
|
279
|
+
const sheet = this.client.sheetsByTitle[table.name];
|
|
280
|
+
yield sheet.loadHeaderRow();
|
|
281
|
+
if (table._rename) {
|
|
282
|
+
const headers = [];
|
|
283
|
+
for (let header of sheet.headerValues) {
|
|
284
|
+
if (header === table._rename.old) {
|
|
285
|
+
headers.push(table._rename.updated);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
headers.push(header);
|
|
262
289
|
}
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
263
292
|
yield sheet.setHeaderRow(headers);
|
|
264
293
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
294
|
+
catch (err) {
|
|
295
|
+
console.error("Error updating column name in google sheets", err);
|
|
296
|
+
throw err;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
const updatedHeaderValues = [...sheet.headerValues];
|
|
301
|
+
// add new column - doesn't currently exist
|
|
302
|
+
for (let [key, column] of Object.entries(table.schema)) {
|
|
303
|
+
if (!ALLOWED_TYPES.includes(column.type)) {
|
|
304
|
+
throw new Error(`Column type: ${column.type} not allowed for GSheets integration.`);
|
|
305
|
+
}
|
|
306
|
+
if (!sheet.headerValues.includes(key) &&
|
|
307
|
+
column.type !== types_1.FieldType.FORMULA) {
|
|
308
|
+
updatedHeaderValues.push(key);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// clear out deleted columns
|
|
312
|
+
for (let key of sheet.headerValues) {
|
|
313
|
+
if (!Object.keys(table.schema).includes(key)) {
|
|
314
|
+
const idx = updatedHeaderValues.indexOf(key);
|
|
315
|
+
updatedHeaderValues.splice(idx, 1);
|
|
270
316
|
}
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
271
319
|
yield sheet.setHeaderRow(updatedHeaderValues);
|
|
272
320
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
321
|
+
catch (err) {
|
|
322
|
+
console.error("Error updating table in google sheets", err);
|
|
323
|
+
throw err;
|
|
324
|
+
}
|
|
277
325
|
}
|
|
278
326
|
});
|
|
279
327
|
}
|
|
@@ -307,6 +355,24 @@ class GoogleSheetsIntegration {
|
|
|
307
355
|
}
|
|
308
356
|
});
|
|
309
357
|
}
|
|
358
|
+
createBulk(query) {
|
|
359
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
360
|
+
try {
|
|
361
|
+
yield this.connect();
|
|
362
|
+
const sheet = this.client.sheetsByTitle[query.sheet];
|
|
363
|
+
let rowsToInsert = [];
|
|
364
|
+
for (let row of query.rows) {
|
|
365
|
+
rowsToInsert.push(typeof row === "string" ? JSON.parse(row) : row);
|
|
366
|
+
}
|
|
367
|
+
const rows = yield sheet.addRows(rowsToInsert);
|
|
368
|
+
return rows.map(row => this.buildRowObject(sheet.headerValues, row._rawData, row._rowNumber));
|
|
369
|
+
}
|
|
370
|
+
catch (err) {
|
|
371
|
+
console.error("Error bulk writing to google sheets", err);
|
|
372
|
+
throw err;
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
}
|
|
310
376
|
read(query) {
|
|
311
377
|
return __awaiter(this, void 0, void 0, function* () {
|
|
312
378
|
try {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.finaliseExternalTables = exports.isIsoDateString = exports.isSQL = exports.getSqlQuery = exports.convertSqlType = exports.breakRowIdField = exports.convertRowId = exports.isRowId = exports.generateRowIdField = exports.breakExternalTableId = exports.buildExternalTableId = exports.isExternalTable = exports.SqlClient = void 0;
|
|
3
|
+
exports.finaliseExternalTables = exports.shouldCopySpecialColumn = exports.shouldCopyRelationship = exports.isIsoDateString = exports.isSQL = exports.getSqlQuery = exports.convertSqlType = exports.breakRowIdField = exports.convertRowId = exports.isRowId = exports.generateRowIdField = exports.breakExternalTableId = exports.buildExternalTableId = exports.isExternalTable = exports.SqlClient = void 0;
|
|
4
4
|
const types_1 = require("@budibase/types");
|
|
5
5
|
const utils_1 = require("../db/utils");
|
|
6
6
|
const constants_1 = require("../constants");
|
|
7
7
|
const DOUBLE_SEPARATOR = `${utils_1.SEPARATOR}${utils_1.SEPARATOR}`;
|
|
8
8
|
const ROW_ID_REGEX = /^\[.*]$/g;
|
|
9
|
+
const ENCODED_SPACE = encodeURIComponent(" ");
|
|
9
10
|
const SQL_NUMBER_TYPE_MAP = {
|
|
10
11
|
integer: constants_1.FieldTypes.NUMBER,
|
|
11
12
|
int: constants_1.FieldTypes.NUMBER,
|
|
@@ -67,6 +68,10 @@ function isExternalTable(tableId) {
|
|
|
67
68
|
}
|
|
68
69
|
exports.isExternalTable = isExternalTable;
|
|
69
70
|
function buildExternalTableId(datasourceId, tableName) {
|
|
71
|
+
// encode spaces
|
|
72
|
+
if (tableName.includes(" ")) {
|
|
73
|
+
tableName = encodeURIComponent(tableName);
|
|
74
|
+
}
|
|
70
75
|
return `${datasourceId}${DOUBLE_SEPARATOR}${tableName}`;
|
|
71
76
|
}
|
|
72
77
|
exports.buildExternalTableId = buildExternalTableId;
|
|
@@ -78,6 +83,10 @@ function breakExternalTableId(tableId) {
|
|
|
78
83
|
let datasourceId = parts.shift();
|
|
79
84
|
// if they need joined
|
|
80
85
|
let tableName = parts.join(DOUBLE_SEPARATOR);
|
|
86
|
+
// if contains encoded spaces, decode it
|
|
87
|
+
if (tableName.includes(ENCODED_SPACE)) {
|
|
88
|
+
tableName = decodeURIComponent(tableName);
|
|
89
|
+
}
|
|
81
90
|
return { datasourceId, tableName };
|
|
82
91
|
}
|
|
83
92
|
exports.breakExternalTableId = breakExternalTableId;
|
|
@@ -193,6 +202,7 @@ function shouldCopyRelationship(column, tableIds) {
|
|
|
193
202
|
column.tableId &&
|
|
194
203
|
tableIds.includes(column.tableId));
|
|
195
204
|
}
|
|
205
|
+
exports.shouldCopyRelationship = shouldCopyRelationship;
|
|
196
206
|
/**
|
|
197
207
|
* Similar function to the shouldCopyRelationship function, but instead this looks for options and boolean
|
|
198
208
|
* types. It is possible to switch a string -> options and a number -> boolean (and vice versus) need to make
|
|
@@ -217,6 +227,7 @@ function shouldCopySpecialColumn(column, fetchedColumn) {
|
|
|
217
227
|
return (specialTypes.indexOf(column.type) !== -1 ||
|
|
218
228
|
(fetchedIsNumber && column.type === constants_1.FieldTypes.BOOLEAN));
|
|
219
229
|
}
|
|
230
|
+
exports.shouldCopySpecialColumn = shouldCopySpecialColumn;
|
|
220
231
|
/**
|
|
221
232
|
* Looks for columns which need to be copied over into the new table definitions, like relationships
|
|
222
233
|
* and options types.
|
|
@@ -226,10 +237,14 @@ function shouldCopySpecialColumn(column, fetchedColumn) {
|
|
|
226
237
|
* @param tableIds The IDs of the tables which exist now, to check if anything has been removed.
|
|
227
238
|
*/
|
|
228
239
|
function copyExistingPropsOver(tableName, table, entities, tableIds) {
|
|
240
|
+
var _a, _b, _c;
|
|
229
241
|
if (entities && entities[tableName]) {
|
|
230
|
-
if (entities[tableName].primaryDisplay) {
|
|
242
|
+
if ((_a = entities[tableName]) === null || _a === void 0 ? void 0 : _a.primaryDisplay) {
|
|
231
243
|
table.primaryDisplay = entities[tableName].primaryDisplay;
|
|
232
244
|
}
|
|
245
|
+
if ((_b = entities[tableName]) === null || _b === void 0 ? void 0 : _b.created) {
|
|
246
|
+
table.created = (_c = entities[tableName]) === null || _c === void 0 ? void 0 : _c.created;
|
|
247
|
+
}
|
|
233
248
|
const existingTableSchema = entities[tableName].schema;
|
|
234
249
|
for (let key in existingTableSchema) {
|
|
235
250
|
if (!existingTableSchema.hasOwnProperty(key)) {
|
package/dist/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/server",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "2.4.
|
|
4
|
+
"version": "2.4.41",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"build:dev": "yarn prebuild && tsc --build --watch --preserveWatchOutput",
|
|
15
15
|
"debug": "yarn build && node --expose-gc --inspect=9222 dist/index.js",
|
|
16
16
|
"postbuild": "copyfiles -u 1 src/**/*.svelte dist/ && copyfiles -u 1 src/**/*.hbs dist/ && copyfiles -u 1 src/**/*.json dist/",
|
|
17
|
-
"test": "bash scripts/test.sh",
|
|
17
|
+
"test": "NODE_OPTIONS=\"--max-old-space-size=4096\" bash scripts/test.sh",
|
|
18
|
+
"test:memory": "jest --maxWorkers=2 --logHeapUsage --forceExit",
|
|
18
19
|
"test:watch": "jest --watch",
|
|
19
20
|
"predocker": "copyfiles -f ../client/dist/budibase-client.js ../client/manifest.json client",
|
|
20
21
|
"build:docker": "yarn run predocker && docker build . -t app-service --label version=$BUDIBASE_RELEASE_VERSION",
|
|
@@ -43,12 +44,12 @@
|
|
|
43
44
|
"license": "GPL-3.0",
|
|
44
45
|
"dependencies": {
|
|
45
46
|
"@apidevtools/swagger-parser": "10.0.3",
|
|
46
|
-
"@budibase/backend-core": "^2.4.
|
|
47
|
-
"@budibase/client": "^2.4.
|
|
48
|
-
"@budibase/pro": "2.4.
|
|
49
|
-
"@budibase/shared-core": "^2.4.
|
|
50
|
-
"@budibase/string-templates": "^2.4.
|
|
51
|
-
"@budibase/types": "^2.4.
|
|
47
|
+
"@budibase/backend-core": "^2.4.41",
|
|
48
|
+
"@budibase/client": "^2.4.41",
|
|
49
|
+
"@budibase/pro": "2.4.40",
|
|
50
|
+
"@budibase/shared-core": "^2.4.41",
|
|
51
|
+
"@budibase/string-templates": "^2.4.41",
|
|
52
|
+
"@budibase/types": "^2.4.41",
|
|
52
53
|
"@bull-board/api": "3.7.0",
|
|
53
54
|
"@bull-board/koa": "3.9.4",
|
|
54
55
|
"@elastic/elasticsearch": "7.10.0",
|
|
@@ -125,7 +126,7 @@
|
|
|
125
126
|
"@babel/core": "7.17.4",
|
|
126
127
|
"@babel/preset-env": "7.16.11",
|
|
127
128
|
"@budibase/standard-components": "^0.9.139",
|
|
128
|
-
"@jest/test-sequencer": "
|
|
129
|
+
"@jest/test-sequencer": "29.5.0",
|
|
129
130
|
"@swc/core": "^1.3.25",
|
|
130
131
|
"@swc/jest": "^0.2.24",
|
|
131
132
|
"@trendyol/jest-testcontainers": "^2.1.1",
|
|
@@ -134,7 +135,7 @@
|
|
|
134
135
|
"@types/global-agent": "2.1.1",
|
|
135
136
|
"@types/google-spreadsheet": "3.1.5",
|
|
136
137
|
"@types/ioredis": "4.28.10",
|
|
137
|
-
"@types/jest": "
|
|
138
|
+
"@types/jest": "29.5.0",
|
|
138
139
|
"@types/koa": "2.13.4",
|
|
139
140
|
"@types/koa__router": "8.0.8",
|
|
140
141
|
"@types/lodash": "4.14.180",
|
|
@@ -154,7 +155,7 @@
|
|
|
154
155
|
"eslint": "6.8.0",
|
|
155
156
|
"ioredis-mock": "7.2.0",
|
|
156
157
|
"is-wsl": "2.2.0",
|
|
157
|
-
"jest": "
|
|
158
|
+
"jest": "29.5.0",
|
|
158
159
|
"jest-openapi": "0.14.2",
|
|
159
160
|
"jest-serial-runner": "^1.2.1",
|
|
160
161
|
"nodemon": "2.0.15",
|
|
@@ -166,7 +167,7 @@
|
|
|
166
167
|
"supertest": "6.2.2",
|
|
167
168
|
"swagger-jsdoc": "6.1.0",
|
|
168
169
|
"timekeeper": "2.2.0",
|
|
169
|
-
"ts-jest": "
|
|
170
|
+
"ts-jest": "29.0.5",
|
|
170
171
|
"ts-node": "10.8.1",
|
|
171
172
|
"tsconfig-paths": "4.0.0",
|
|
172
173
|
"typescript": "4.7.3",
|
package/dist/sdk/users/utils.js
CHANGED
|
@@ -16,7 +16,8 @@ const utils_1 = require("../../db/utils");
|
|
|
16
16
|
const lodash_1 = require("lodash");
|
|
17
17
|
function combineMetadataAndUser(user, metadata) {
|
|
18
18
|
// skip users with no access
|
|
19
|
-
if (user.roleId
|
|
19
|
+
if (user.roleId == null ||
|
|
20
|
+
user.roleId === backend_core_1.roles.BUILTIN_ROLE_IDS.PUBLIC) {
|
|
20
21
|
return null;
|
|
21
22
|
}
|
|
22
23
|
delete user._rev;
|