@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.
Files changed (75) hide show
  1. package/__mocks__/node-fetch.ts +6 -1
  2. package/builder/assets/index.3cb1022d.css +6 -0
  3. package/builder/assets/{index.07ed2ead.js → index.4b6c8c0e.js} +384 -383
  4. package/builder/index.html +7 -7
  5. package/dist/api/controllers/application.js +28 -24
  6. package/dist/api/controllers/datasource.js +2 -1
  7. package/dist/api/controllers/public/metrics.js +113 -0
  8. package/dist/api/controllers/row/external.js +16 -8
  9. package/dist/api/controllers/row/index.js +11 -1
  10. package/dist/api/controllers/row/internal.js +1 -10
  11. package/dist/api/controllers/row/utils.js +7 -7
  12. package/dist/api/controllers/static/index.js +84 -24
  13. package/dist/api/controllers/static/templates/BudibaseApp.svelte +33 -10
  14. package/dist/api/controllers/table/external.js +16 -12
  15. package/dist/api/controllers/table/utils.js +15 -1
  16. package/dist/api/routes/public/index.js +8 -0
  17. package/dist/api/routes/public/metrics.js +30 -0
  18. package/dist/app.js +1 -0
  19. package/dist/constants/index.js +2 -1
  20. package/dist/integrations/googlesheets.js +125 -59
  21. package/dist/integrations/redis.js +1 -1
  22. package/dist/integrations/utils.js +17 -2
  23. package/dist/package.json +13 -12
  24. package/dist/sdk/users/utils.js +2 -1
  25. package/dist/tsconfig.build.tsbuildinfo +1 -1
  26. package/dist/utilities/global.js +17 -7
  27. package/jest.config.ts +1 -0
  28. package/package.json +14 -13
  29. package/scripts/test.sh +3 -3
  30. package/specs/openapi.json +39 -0
  31. package/specs/openapi.yaml +169 -0
  32. package/specs/resources/application.ts +11 -0
  33. package/specs/resources/index.ts +2 -0
  34. package/specs/resources/metrics.ts +81 -0
  35. package/src/api/controllers/application.ts +20 -21
  36. package/src/api/controllers/datasource.ts +2 -1
  37. package/src/api/controllers/public/metrics.ts +251 -0
  38. package/src/api/controllers/row/external.ts +26 -16
  39. package/src/api/controllers/row/index.ts +12 -2
  40. package/src/api/controllers/row/internal.ts +0 -7
  41. package/src/api/controllers/row/utils.ts +7 -7
  42. package/src/api/controllers/static/index.ts +69 -26
  43. package/src/api/controllers/static/templates/BudibaseApp.svelte +33 -10
  44. package/src/api/controllers/table/external.ts +24 -17
  45. package/src/api/controllers/table/index.ts +9 -9
  46. package/src/api/controllers/table/utils.ts +18 -2
  47. package/src/api/controllers/view/tests/__snapshots__/viewBuilder.spec.js.snap +48 -48
  48. package/src/api/routes/public/index.ts +10 -1
  49. package/src/api/routes/public/metrics.ts +28 -0
  50. package/src/api/routes/public/tests/metrics.spec.js +34 -0
  51. package/src/api/routes/tests/__snapshots__/datasource.spec.ts.snap +22 -22
  52. package/src/api/routes/tests/__snapshots__/view.spec.js.snap +5 -5
  53. package/src/api/routes/tests/appSync.spec.ts +31 -0
  54. package/src/api/routes/tests/internalSearch.spec.js +8 -7
  55. package/src/app.ts +2 -1
  56. package/src/automations/automationUtils.ts +1 -1
  57. package/src/automations/tests/automation.spec.ts +99 -0
  58. package/src/constants/index.ts +1 -0
  59. package/src/definitions/openapi.ts +15 -0
  60. package/src/integration-test/postgres.spec.ts +46 -52
  61. package/src/integrations/googlesheets.ts +143 -71
  62. package/src/integrations/redis.ts +1 -1
  63. package/src/integrations/tests/googlesheets.spec.ts +13 -13
  64. package/src/integrations/tests/redis.spec.ts +9 -5
  65. package/src/integrations/utils.ts +16 -4
  66. package/src/middleware/currentapp.ts +2 -2
  67. package/src/sdk/users/utils.ts +4 -1
  68. package/src/tests/jestEnv.ts +1 -0
  69. package/src/tests/jestSetup.ts +5 -1
  70. package/src/tests/utilities/TestConfiguration.ts +13 -0
  71. package/src/tests/utilities/structures.ts +13 -1
  72. package/src/utilities/global.ts +21 -9
  73. package/builder/assets/favicon.e7fc7733.png +0 -0
  74. package/builder/assets/index.b0e3aca6.css +0 -6
  75. package/src/automations/tests/automation.spec.js +0 -84
@@ -1,19 +1,19 @@
1
1
  <!doctype html>
2
2
  <html class="spectrum spectrum--medium spectrum--darkest" lang="en" dir="ltr">
3
+
3
4
  <head>
4
5
  <meta charset='utf8'>
5
6
  <meta name='viewport' content='width=device-width'>
6
7
  <title>Budibase</title>
7
- <link rel='icon' href='/builder/assets/favicon.e7fc7733.png'>
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" />
9
- <link
10
- href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap"
11
- rel="stylesheet"
12
- />
13
- <script type="module" crossorigin src="/builder/assets/index.07ed2ead.js"></script>
14
- <link rel="stylesheet" href="/builder/assets/index.b0e3aca6.css">
9
+ <link href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap"
10
+ rel="stylesheet" />
11
+ <script type="module" crossorigin src="/builder/assets/index.4b6c8c0e.js"></script>
12
+ <link rel="stylesheet" href="/builder/assets/index.3cb1022d.css">
15
13
  </head>
14
+
16
15
  <body id="app">
17
16
 
18
17
  </body>
18
+
19
19
  </html>
@@ -320,7 +320,7 @@ function appPostCreate(ctx, app) {
320
320
  });
321
321
  }
322
322
  catch (err) {
323
- if (err.code && err.code === backend_core_1.errors.codes.USAGE_LIMIT_EXCEEDED) {
323
+ if (err.code && err.code === backend_core_1.ErrorCode.USAGE_LIMIT_EXCEEDED) {
324
324
  // this import resulted in row usage exceeding the quota
325
325
  // delete the app
326
326
  // skip pre and post-steps as no rows have been added to quotas yet
@@ -415,17 +415,19 @@ function revertClient(ctx) {
415
415
  });
416
416
  }
417
417
  exports.revertClient = revertClient;
418
- const unpublishApp = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
419
- let appId = ctx.params.appId;
420
- appId = backend_core_1.db.getProdAppID(appId);
421
- const db = backend_core_1.context.getProdAppDB();
422
- const result = yield db.destroy();
423
- yield backend_core_1.events.app.unpublished({ appId });
424
- // automations only in production
425
- yield (0, utils_2.cleanupAutomations)(appId);
426
- yield backend_core_1.cache.app.invalidateAppMetadata(appId);
427
- return result;
428
- });
418
+ function unpublishApp(ctx) {
419
+ return __awaiter(this, void 0, void 0, function* () {
420
+ let appId = ctx.params.appId;
421
+ appId = backend_core_1.db.getProdAppID(appId);
422
+ const db = backend_core_1.context.getProdAppDB();
423
+ const result = yield db.destroy();
424
+ yield backend_core_1.events.app.unpublished({ appId });
425
+ // automations only in production
426
+ yield (0, utils_2.cleanupAutomations)(appId);
427
+ yield backend_core_1.cache.app.invalidateAppMetadata(appId);
428
+ return result;
429
+ });
430
+ }
429
431
  function destroyApp(ctx) {
430
432
  return __awaiter(this, void 0, void 0, function* () {
431
433
  let appId = ctx.params.appId;
@@ -476,18 +478,20 @@ function destroy(ctx) {
476
478
  });
477
479
  }
478
480
  exports.destroy = destroy;
479
- const unpublish = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
480
- const prodAppId = backend_core_1.db.getProdAppID(ctx.params.appId);
481
- const dbExists = yield backend_core_1.db.dbExists(prodAppId);
482
- // check app has been published
483
- if (!dbExists) {
484
- return ctx.throw(400, "App has not been published.");
485
- }
486
- yield preDestroyApp(ctx);
487
- yield unpublishApp(ctx);
488
- yield postDestroyApp(ctx);
489
- ctx.status = 204;
490
- });
481
+ function unpublish(ctx) {
482
+ return __awaiter(this, void 0, void 0, function* () {
483
+ const prodAppId = backend_core_1.db.getProdAppID(ctx.params.appId);
484
+ const dbExists = yield backend_core_1.db.dbExists(prodAppId);
485
+ // check app has been published
486
+ if (!dbExists) {
487
+ return ctx.throw(400, "App has not been published.");
488
+ }
489
+ yield preDestroyApp(ctx);
490
+ yield unpublishApp(ctx);
491
+ yield postDestroyApp(ctx);
492
+ ctx.status = 204;
493
+ });
494
+ }
491
495
  exports.unpublish = unpublish;
492
496
  function sync(ctx) {
493
497
  return __awaiter(this, void 0, void 0, function* () {
@@ -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 response = { datasource };
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
  }
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.convertToOpenMetrics = exports.fetch = void 0;
16
+ const backend_core_1 = require("@budibase/backend-core");
17
+ const pro_1 = require("@budibase/pro");
18
+ const os_1 = __importDefault(require("os"));
19
+ function fetch(ctx) {
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ // *** OPERATING SYSTEM ***
22
+ const freeMem = os_1.default.freemem();
23
+ const totalMem = os_1.default.totalmem();
24
+ const usedMem = totalMem - freeMem;
25
+ const uptime = os_1.default.uptime();
26
+ // *** APPS ***
27
+ const allDatabases = yield backend_core_1.db.getAllDbs();
28
+ const devAppIDs = yield backend_core_1.db.getDevAppIDs();
29
+ const prodAppIDs = yield backend_core_1.db.getProdAppIDs();
30
+ const allAppIds = yield backend_core_1.db.getAllApps({ idsOnly: true });
31
+ // *** USERS ***
32
+ const usersObject = yield backend_core_1.users.getAllUserIds();
33
+ // *** QUOTAS ***
34
+ const usage = yield pro_1.quotas.getQuotaUsage();
35
+ const license = yield pro_1.licensing.cache.getCachedLicense();
36
+ const appsQuotaUsage = usage.usageQuota.apps;
37
+ const rowsQuotaUsage = usage.usageQuota.rows;
38
+ const pluginsQuotaUsage = usage.usageQuota.plugins;
39
+ const userGroupsQuotaUsage = usage.usageQuota.userGroups;
40
+ const queryQuotaUsage = usage.monthly.current.queries;
41
+ const automationsQuotaUsage = usage.monthly.current.automations;
42
+ const appsQuotaLimit = license.quotas.usage.static.apps.value;
43
+ const rowsQuotaLimit = license.quotas.usage.static.rows.value;
44
+ const userGroupsQuotaLimit = license.quotas.usage.static.userGroups.value;
45
+ const pluginsQuotaLimit = license.quotas.usage.static.plugins.value;
46
+ const queryQuotaLimit = license.quotas.usage.monthly.queries.value;
47
+ const automationsQuotaLimit = license.quotas.usage.monthly.automations.value;
48
+ // *** BUILD THE OUTPUT STRING ***
49
+ var outputString = "";
50
+ // **** budibase_os_uptime ****
51
+ outputString += convertToOpenMetrics("budibase_os_uptime", "Time in seconds that the host operating system has been up", "counter", uptime);
52
+ // **** budibase_os_free_mem ****
53
+ outputString += convertToOpenMetrics("budibase_os_free_mem", "Bytes of memory free for usage on the host operating system", "gauge", freeMem);
54
+ // **** budibase_os_total_mem ****
55
+ outputString += convertToOpenMetrics("budibase_os_total_mem", "Total bytes of memory on the host operating system", "gauge", totalMem);
56
+ // **** budibase_os_used_mem ****
57
+ outputString += convertToOpenMetrics("budibase_os_used_mem", "Total bytes of memory in use on the host operating system", "gauge", usedMem);
58
+ // **** budibase_os_load1 ****
59
+ outputString += convertToOpenMetrics("budibase_os_load1", "Host operating system load average", "gauge", os_1.default.loadavg()[0]);
60
+ // **** budibase_os_load5 ****
61
+ outputString += convertToOpenMetrics("budibase_os_load5", "Host operating system load average", "gauge", os_1.default.loadavg()[1]);
62
+ // **** budibase_os_load15 ****
63
+ outputString += convertToOpenMetrics("budibase_os_load15", "Host operating system load average", "gauge", os_1.default.loadavg()[2]);
64
+ // **** budibase_tenant_user_count ****
65
+ outputString += convertToOpenMetrics("budibase_tenant_user_count", "The number of users created", "gauge", usersObject.length);
66
+ // **** budibase_tenant_app_count ****
67
+ outputString += convertToOpenMetrics("budibase_tenant_app_count", "The number of apps created by a user", "gauge", allAppIds.length);
68
+ // **** budibase_tenant_production_app_count ****
69
+ outputString += convertToOpenMetrics("budibase_tenant_production_app_count", "The number of apps a user has published", "gauge", prodAppIDs.length);
70
+ // **** budibase_tenant_dev_app_count ****
71
+ outputString += convertToOpenMetrics("budibase_tenant_dev_app_count", "The number of apps a user has unpublished in development", "gauge", devAppIDs.length);
72
+ // **** budibase_tenant_db_count ****
73
+ outputString += convertToOpenMetrics("budibase_tenant_db_count", "The number of couchdb databases including global tables such as _users", "gauge", allDatabases.length);
74
+ // **** budibase_quota_usage_apps ****
75
+ outputString += convertToOpenMetrics("budibase_quota_usage_apps", "The number of apps created", "gauge", appsQuotaUsage);
76
+ // **** budibase_quota_limit_apps ****
77
+ outputString += convertToOpenMetrics("budibase_quota_limit_apps", "The limit on the number of apps that can be created", "gauge", appsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : appsQuotaLimit);
78
+ // **** budibase_quota_usage_rows ****
79
+ outputString += convertToOpenMetrics("budibase_quota_usage_rows", "The number of database rows used from the quota", "gauge", rowsQuotaUsage);
80
+ // **** budibase_quota_limit_rows ****
81
+ outputString += convertToOpenMetrics("budibase_quota_limit_rows", "The limit on the number of rows that can be created", "gauge", rowsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : rowsQuotaLimit);
82
+ // **** budibase_quota_usage_plugins ****
83
+ outputString += convertToOpenMetrics("budibase_quota_usage_plugins", "The number of plugins in use", "gauge", pluginsQuotaUsage);
84
+ // **** budibase_quota_limit_plugins ****
85
+ outputString += convertToOpenMetrics("budibase_quota_limit_plugins", "The limit on the number of plugins that can be created", "gauge", pluginsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : pluginsQuotaLimit);
86
+ // **** budibase_quota_usage_user_groups ****
87
+ outputString += convertToOpenMetrics("budibase_quota_usage_user_groups", "The number of user groups created", "gauge", userGroupsQuotaUsage);
88
+ // **** budibase_quota_limit_user_groups ****
89
+ outputString += convertToOpenMetrics("budibase_quota_limit_user_groups", "The limit on the number of user groups that can be created", "gauge", userGroupsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : userGroupsQuotaLimit);
90
+ // **** budibase_quota_usage_queries ****
91
+ outputString += convertToOpenMetrics("budibase_quota_usage_queries", "The number of queries used in the current month", "gauge", queryQuotaUsage);
92
+ // **** budibase_quota_limit_queries ****
93
+ outputString += convertToOpenMetrics("budibase_quota_limit_queries", "The limit on the number of queries for the current month", "gauge", queryQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : queryQuotaLimit);
94
+ // **** budibase_quota_usage_automations ****
95
+ outputString += convertToOpenMetrics("budibase_quota_usage_automations", "The number of automations used in the current month", "gauge", automationsQuotaUsage);
96
+ // **** budibase_quota_limit_automations ****
97
+ outputString += convertToOpenMetrics("budibase_quota_limit_automations", "The limit on the number of automations that can be created", "gauge", automationsQuotaLimit == -1
98
+ ? Number.MAX_SAFE_INTEGER
99
+ : automationsQuotaLimit);
100
+ ctx.body = outputString;
101
+ ctx.set("Content-Type", "text/plain");
102
+ });
103
+ }
104
+ exports.fetch = fetch;
105
+ function convertToOpenMetrics(metricName, metricHelp, metricType, metricValue) {
106
+ return `# HELP ${metricName} ${metricHelp}.
107
+ # TYPE ${metricName} ${metricType}
108
+ ${metricName} ${metricValue}\n`;
109
+ }
110
+ exports.convertToOpenMetrics = convertToOpenMetrics;
111
+ exports.default = {
112
+ fetch,
113
+ };
@@ -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.validate = exports.search = exports.bulkDestroy = exports.destroy = exports.find = exports.fetch = exports.fetchView = exports.save = exports.patch = exports.handleRequest = void 0;
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");
@@ -54,6 +54,7 @@ const exporters = __importStar(require("../view/exporters"));
54
54
  const fileSystem_1 = require("../../../utilities/fileSystem");
55
55
  const types_1 = require("@budibase/types");
56
56
  const sdk_1 = __importDefault(require("../../../sdk"));
57
+ const utils = __importStar(require("./utils"));
57
58
  const { cleanExportRows } = require("./utils");
58
59
  function handleRequest(operation, tableId, opts) {
59
60
  return __awaiter(this, void 0, void 0, function* () {
@@ -83,6 +84,13 @@ function patch(ctx) {
83
84
  const id = inputs._id;
84
85
  // don't save the ID to db
85
86
  delete inputs._id;
87
+ const validateResult = yield utils.validate({
88
+ row: inputs,
89
+ tableId,
90
+ });
91
+ if (!validateResult.valid) {
92
+ throw { validation: validateResult.errors };
93
+ }
86
94
  return handleRequest(types_1.Operation.UPDATE, tableId, {
87
95
  id: (0, utils_1.breakRowIdField)(id),
88
96
  row: inputs,
@@ -95,6 +103,13 @@ function save(ctx) {
95
103
  return __awaiter(this, void 0, void 0, function* () {
96
104
  const inputs = ctx.request.body;
97
105
  const tableId = ctx.params.tableId;
106
+ const validateResult = yield utils.validate({
107
+ row: inputs,
108
+ tableId,
109
+ });
110
+ if (!validateResult.valid) {
111
+ throw { validation: validateResult.errors };
112
+ }
98
113
  return handleRequest(types_1.Operation.CREATE, tableId, {
99
114
  row: inputs,
100
115
  includeSqlRelationships: types_1.IncludeRelationship.EXCLUDE,
@@ -225,13 +240,6 @@ function search(ctx) {
225
240
  });
226
241
  }
227
242
  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
243
  function exportRows(ctx) {
236
244
  return __awaiter(this, void 0, void 0, function* () {
237
245
  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
- ctx.body = yield pickApi(tableId).validate(ctx);
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.validate = exports.search = exports.bulkDestroy = exports.destroy = exports.find = exports.fetch = exports.fetchView = exports.save = exports.patch = void 0;
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,18 +88,18 @@ function validate({ tableId, row, table, }) {
88
88
  return __awaiter(this, void 0, void 0, function* () {
89
89
  let fetchedTable;
90
90
  if (!table) {
91
- const db = backend_core_1.context.getAppDB();
92
- fetchedTable = yield db.get(tableId);
91
+ fetchedTable = yield sdk_1.default.tables.getTable(tableId);
93
92
  }
94
93
  else {
95
94
  fetchedTable = table;
96
95
  }
97
96
  const errors = {};
98
97
  for (let fieldName of Object.keys(fetchedTable.schema)) {
99
- const constraints = cloneDeep(fetchedTable.schema[fieldName].constraints);
100
- const type = fetchedTable.schema[fieldName].type;
98
+ const column = fetchedTable.schema[fieldName];
99
+ const constraints = cloneDeep(column.constraints);
100
+ const type = column.type;
101
101
  // formulas shouldn't validated, data will be deleted anyway
102
- if (type === constants_1.FieldTypes.FORMULA) {
102
+ if (type === constants_1.FieldTypes.FORMULA || column.autocolumn) {
103
103
  continue;
104
104
  }
105
105
  // special case for options, need to always allow unselected (null)
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -25,6 +48,7 @@ const backend_core_1 = require("@budibase/backend-core");
25
48
  const aws_sdk_1 = __importDefault(require("aws-sdk"));
26
49
  const fs_1 = __importDefault(require("fs"));
27
50
  const sdk_1 = __importDefault(require("../../../sdk"));
51
+ const pro = __importStar(require("@budibase/pro"));
28
52
  const send = require("koa-send");
29
53
  function prepareUpload({ s3Key, bucket, metadata, file }) {
30
54
  return __awaiter(this, void 0, void 0, function* () {
@@ -102,31 +126,67 @@ const deleteObjects = function (ctx) {
102
126
  exports.deleteObjects = deleteObjects;
103
127
  const serveApp = function (ctx) {
104
128
  return __awaiter(this, void 0, void 0, function* () {
105
- const db = backend_core_1.context.getAppDB({ skip_setup: true });
106
- const appInfo = yield db.get(utils_1.DocumentType.APP_METADATA);
107
- let appId = backend_core_1.context.getAppId();
108
- if (!environment_1.default.isJest()) {
109
- const App = require("./templates/BudibaseApp.svelte").default;
110
- const plugins = backend_core_1.objectStore.enrichPluginURLs(appInfo.usedPlugins);
111
- const { head, html, css } = App.render({
112
- metaImage: "https://res.cloudinary.com/daog6scxm/image/upload/v1666109324/meta-images/budibase-meta-image_uukc1m.png",
113
- title: appInfo.name,
114
- production: environment_1.default.isProd(),
115
- appId,
116
- clientLibPath: backend_core_1.objectStore.clientLibraryUrl(appId, appInfo.version),
117
- usedPlugins: plugins,
118
- });
119
- const appHbs = (0, fileSystem_1.loadHandlebarsFile)(`${__dirname}/templates/app.hbs`);
120
- ctx.body = yield (0, string_templates_1.processString)(appHbs, {
121
- head,
122
- body: html,
123
- style: css.code,
124
- appId,
125
- });
129
+ //Public Settings
130
+ const { config } = yield backend_core_1.configs.getSettingsConfigDoc();
131
+ const branding = yield pro.branding.getBrandingConfig(config);
132
+ let db;
133
+ try {
134
+ db = backend_core_1.context.getAppDB({ skip_setup: true });
135
+ const appInfo = yield db.get(utils_1.DocumentType.APP_METADATA);
136
+ let appId = backend_core_1.context.getAppId();
137
+ if (!environment_1.default.isJest()) {
138
+ const App = require("./templates/BudibaseApp.svelte").default;
139
+ const plugins = backend_core_1.objectStore.enrichPluginURLs(appInfo.usedPlugins);
140
+ const { head, html, css } = App.render({
141
+ metaImage: (branding === null || branding === void 0 ? void 0 : branding.metaImageUrl) ||
142
+ "https://res.cloudinary.com/daog6scxm/image/upload/v1666109324/meta-images/budibase-meta-image_uukc1m.png",
143
+ metaDescription: (branding === null || branding === void 0 ? void 0 : branding.metaDescription) || "",
144
+ metaTitle: (branding === null || branding === void 0 ? void 0 : branding.metaTitle) || `${appInfo.name} - built with Budibase`,
145
+ title: appInfo.name,
146
+ production: environment_1.default.isProd(),
147
+ appId,
148
+ clientLibPath: backend_core_1.objectStore.clientLibraryUrl(appId, appInfo.version),
149
+ usedPlugins: plugins,
150
+ favicon: branding.faviconUrl !== ""
151
+ ? backend_core_1.objectStore.getGlobalFileUrl("settings", "faviconUrl")
152
+ : "",
153
+ logo: (config === null || config === void 0 ? void 0 : config.logoUrl) !== ""
154
+ ? backend_core_1.objectStore.getGlobalFileUrl("settings", "logoUrl")
155
+ : "",
156
+ });
157
+ const appHbs = (0, fileSystem_1.loadHandlebarsFile)(`${__dirname}/templates/app.hbs`);
158
+ ctx.body = yield (0, string_templates_1.processString)(appHbs, {
159
+ head,
160
+ body: html,
161
+ style: css.code,
162
+ appId,
163
+ });
164
+ }
165
+ else {
166
+ // just return the app info for jest to assert on
167
+ ctx.body = appInfo;
168
+ }
126
169
  }
127
- else {
128
- // just return the app info for jest to assert on
129
- ctx.body = appInfo;
170
+ catch (error) {
171
+ if (!environment_1.default.isJest()) {
172
+ const App = require("./templates/BudibaseApp.svelte").default;
173
+ const { head, html, css } = App.render({
174
+ title: branding === null || branding === void 0 ? void 0 : branding.metaTitle,
175
+ metaTitle: branding === null || branding === void 0 ? void 0 : branding.metaTitle,
176
+ metaImage: (branding === null || branding === void 0 ? void 0 : branding.metaImageUrl) ||
177
+ "https://res.cloudinary.com/daog6scxm/image/upload/v1666109324/meta-images/budibase-meta-image_uukc1m.png",
178
+ metaDescription: (branding === null || branding === void 0 ? void 0 : branding.metaDescription) || "",
179
+ favicon: branding.faviconUrl !== ""
180
+ ? backend_core_1.objectStore.getGlobalFileUrl("settings", "faviconUrl")
181
+ : "",
182
+ });
183
+ const appHbs = (0, fileSystem_1.loadHandlebarsFile)(`${__dirname}/templates/app.hbs`);
184
+ ctx.body = yield (0, string_templates_1.processString)(appHbs, {
185
+ head,
186
+ body: html,
187
+ style: css.code,
188
+ });
189
+ }
130
190
  }
131
191
  });
132
192
  };
@@ -1,7 +1,10 @@
1
1
  <script>
2
2
  export let title = ""
3
3
  export let favicon = ""
4
+
4
5
  export let metaImage = ""
6
+ export let metaTitle = ""
7
+ export let metaDescription = ""
5
8
 
6
9
  export let clientLibPath
7
10
  export let usedPlugins
@@ -13,18 +16,33 @@
13
16
  name="viewport"
14
17
  content="width=device-width, initial-scale=1.0, viewport-fit=cover"
15
18
  />
19
+
20
+ <!-- Primary Meta Tags -->
21
+ <meta name="title" content={metaTitle} />
22
+ <meta name="description" content={metaDescription} />
23
+
16
24
  <!-- Opengraph Meta Tags -->
17
- <meta name="twitter:card" content="summary_large_image" />
18
- <meta name="twitter:site" content="@budibase" />
19
- <meta name="twitter:image" content={metaImage} />
20
- <meta name="twitter:title" content="{title} - built with Budibase" />
21
25
  <meta property="og:site_name" content="Budibase" />
22
26
  <meta property="og:title" content="{title} - built with Budibase" />
27
+ <meta property="og:description" content={metaDescription} />
23
28
  <meta property="og:type" content="website" />
24
29
  <meta property="og:image" content={metaImage} />
25
30
 
31
+ <!-- Twitter -->
32
+ <meta property="twitter:card" content="summary_large_image" />
33
+ <meta property="twitter:site" content="@budibase" />
34
+ <meta property="twitter:image" content={metaImage} />
35
+ <meta property="twitter:image:alt" content="{title} - built with Budibase" />
36
+ <meta property="twitter:title" content="{title} - built with Budibase" />
37
+ <meta property="twitter:description" content={metaDescription} />
38
+
26
39
  <title>{title}</title>
27
- <link rel="icon" type="image/png" href={favicon} />
40
+ {#if favicon !== ""}
41
+ <link rel="icon" type="image/png" href={favicon} />
42
+ {:else}
43
+ <link rel="icon" type="image/png" href="https://i.imgur.com/Xhdt1YP.png" />
44
+ {/if}
45
+
28
46
  <link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
29
47
  <link rel="preconnect" href="https://fonts.gstatic.com" />
30
48
  <link
@@ -83,11 +101,16 @@
83
101
 
84
102
  <body id="app">
85
103
  <div id="error">
86
- <h1>There was an error loading your app</h1>
87
- <h2>
88
- The Budibase client library could not be loaded. Try republishing your
89
- app.
90
- </h2>
104
+ {#if clientLibPath}
105
+ <h1>There was an error loading your app</h1>
106
+ <h2>
107
+ The Budibase client library could not be loaded. Try republishing your
108
+ app.
109
+ </h2>
110
+ {:else}
111
+ <h2>We couldn't find that application</h2>
112
+ <p />
113
+ {/if}
91
114
  </div>
92
115
  <script type="application/javascript">
93
116
  window.INIT_TIME = Date.now()