@budibase/server 2.4.40 → 2.4.41
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/builder/assets/{index.07ed2ead.js → index.cf8e1455.js} +277 -276
- package/builder/index.html +1 -1
- package/dist/api/controllers/datasource.js +2 -1
- package/dist/api/controllers/row/external.js +1 -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 +3 -4
- package/dist/api/controllers/table/external.js +16 -12
- package/dist/api/controllers/table/utils.js +15 -1
- package/dist/constants/index.js +2 -1
- package/dist/integrations/googlesheets.js +125 -59
- package/dist/integrations/utils.js +17 -2
- package/dist/package.json +7 -7
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/api/controllers/datasource.ts +2 -1
- package/src/api/controllers/row/external.ts +12 -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 +3 -4
- 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/constants/index.ts +1 -0
- package/src/integrations/googlesheets.ts +143 -71
- package/src/integrations/utils.ts +16 -4
package/builder/index.html
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
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.
|
|
13
|
+
<script type="module" crossorigin src="/builder/assets/index.cf8e1455.js"></script>
|
|
14
14
|
<link rel="stylesheet" href="/builder/assets/index.b0e3aca6.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body id="app">
|
|
@@ -74,7 +74,8 @@ function buildSchemaFromDb(ctx) {
|
|
|
74
74
|
setDefaultDisplayColumns(datasource);
|
|
75
75
|
const dbResp = yield db.put(datasource);
|
|
76
76
|
datasource._rev = dbResp.rev;
|
|
77
|
-
const
|
|
77
|
+
const cleanedDatasource = yield sdk_1.default.datasources.removeSecretSingle(datasource);
|
|
78
|
+
const response = { datasource: cleanedDatasource };
|
|
78
79
|
if (error) {
|
|
79
80
|
response.error = error;
|
|
80
81
|
}
|
|
@@ -46,7 +46,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
46
46
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
47
|
};
|
|
48
48
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
-
exports.fetchEnrichedRow = exports.exportRows = exports.
|
|
49
|
+
exports.fetchEnrichedRow = exports.exportRows = exports.search = exports.bulkDestroy = exports.destroy = exports.find = exports.fetch = exports.fetchView = exports.save = exports.patch = exports.handleRequest = void 0;
|
|
50
50
|
const constants_1 = require("../../../constants");
|
|
51
51
|
const utils_1 = require("../../../integrations/utils");
|
|
52
52
|
const ExternalRequest_1 = require("./ExternalRequest");
|
|
@@ -225,13 +225,6 @@ function search(ctx) {
|
|
|
225
225
|
});
|
|
226
226
|
}
|
|
227
227
|
exports.search = search;
|
|
228
|
-
function validate(ctx) {
|
|
229
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
230
|
-
// can't validate external right now - maybe in future
|
|
231
|
-
return { valid: true };
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
exports.validate = validate;
|
|
235
228
|
function exportRows(ctx) {
|
|
236
229
|
return __awaiter(this, void 0, void 0, function* () {
|
|
237
230
|
const { datasourceId, tableName } = (0, utils_1.breakExternalTableId)(ctx.params.tableId);
|
|
@@ -37,6 +37,7 @@ const pro_1 = require("@budibase/pro");
|
|
|
37
37
|
const internal = __importStar(require("./internal"));
|
|
38
38
|
const external = __importStar(require("./external"));
|
|
39
39
|
const utils_1 = require("../../../integrations/utils");
|
|
40
|
+
const utils = __importStar(require("./utils"));
|
|
40
41
|
function pickApi(tableId) {
|
|
41
42
|
if ((0, utils_1.isExternalTable)(tableId)) {
|
|
42
43
|
return external;
|
|
@@ -171,7 +172,16 @@ exports.search = search;
|
|
|
171
172
|
function validate(ctx) {
|
|
172
173
|
return __awaiter(this, void 0, void 0, function* () {
|
|
173
174
|
const tableId = getTableId(ctx);
|
|
174
|
-
|
|
175
|
+
// external tables are hard to validate currently
|
|
176
|
+
if ((0, utils_1.isExternalTable)(tableId)) {
|
|
177
|
+
ctx.body = { valid: true };
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
ctx.body = yield utils.validate({
|
|
181
|
+
row: ctx.request.body,
|
|
182
|
+
tableId,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
175
185
|
});
|
|
176
186
|
}
|
|
177
187
|
exports.validate = validate;
|
|
@@ -46,7 +46,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
46
46
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
47
|
};
|
|
48
48
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
-
exports.fetchEnrichedRow = exports.exportRows = exports.
|
|
49
|
+
exports.fetchEnrichedRow = exports.exportRows = exports.search = exports.bulkDestroy = exports.destroy = exports.find = exports.fetch = exports.fetchView = exports.save = exports.patch = void 0;
|
|
50
50
|
const linkRows = __importStar(require("../../../db/linkedRows"));
|
|
51
51
|
const utils_1 = require("../../../db/utils");
|
|
52
52
|
const userController = __importStar(require("../user"));
|
|
@@ -392,15 +392,6 @@ function search(ctx) {
|
|
|
392
392
|
});
|
|
393
393
|
}
|
|
394
394
|
exports.search = search;
|
|
395
|
-
function validate(ctx) {
|
|
396
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
397
|
-
return utils.validate({
|
|
398
|
-
tableId: ctx.params.tableId,
|
|
399
|
-
row: ctx.request.body,
|
|
400
|
-
});
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
exports.validate = validate;
|
|
404
395
|
function exportRows(ctx) {
|
|
405
396
|
return __awaiter(this, void 0, void 0, function* () {
|
|
406
397
|
const db = backend_core_1.context.getAppDB();
|
|
@@ -41,10 +41,10 @@ const userController = __importStar(require("../user"));
|
|
|
41
41
|
const constants_1 = require("../../../constants");
|
|
42
42
|
const backend_core_1 = require("@budibase/backend-core");
|
|
43
43
|
const query_1 = require("../../../integrations/base/query");
|
|
44
|
-
const validateJs = require("validate.js");
|
|
45
|
-
const { cloneDeep } = require("lodash/fp");
|
|
46
44
|
const exporters_1 = require("../view/exporters");
|
|
47
45
|
const sdk_1 = __importDefault(require("../../../sdk"));
|
|
46
|
+
const validateJs = require("validate.js");
|
|
47
|
+
const { cloneDeep } = require("lodash/fp");
|
|
48
48
|
validateJs.extend(validateJs.validators.datetime, {
|
|
49
49
|
parse: function (value) {
|
|
50
50
|
return new Date(value).getTime();
|
|
@@ -88,8 +88,7 @@ function validate({ tableId, row, table, }) {
|
|
|
88
88
|
return __awaiter(this, void 0, void 0, function* () {
|
|
89
89
|
let fetchedTable;
|
|
90
90
|
if (!table) {
|
|
91
|
-
|
|
92
|
-
fetchedTable = yield db.get(tableId);
|
|
91
|
+
fetchedTable = yield sdk_1.default.tables.getTable(tableId);
|
|
93
92
|
}
|
|
94
93
|
else {
|
|
95
94
|
fetchedTable = table;
|
|
@@ -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;
|
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.40",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -43,12 +43,12 @@
|
|
|
43
43
|
"license": "GPL-3.0",
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@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.
|
|
46
|
+
"@budibase/backend-core": "^2.4.40",
|
|
47
|
+
"@budibase/client": "^2.4.40",
|
|
48
|
+
"@budibase/pro": "2.4.40",
|
|
49
|
+
"@budibase/shared-core": "^2.4.40",
|
|
50
|
+
"@budibase/string-templates": "^2.4.40",
|
|
51
|
+
"@budibase/types": "^2.4.40",
|
|
52
52
|
"@bull-board/api": "3.7.0",
|
|
53
53
|
"@bull-board/koa": "3.9.4",
|
|
54
54
|
"@elastic/elasticsearch": "7.10.0",
|