@budibase/server 2.5.5-alpha.4 → 2.5.5

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 (49) hide show
  1. package/builder/assets/{index.841e62d8.css → index.7f9a008b.css} +3 -3
  2. package/builder/assets/index.f493a2b3.js +1817 -0
  3. package/builder/index.html +2 -2
  4. package/dist/api/routes/index.js +0 -2
  5. package/dist/app.js +11 -2
  6. package/dist/elasticApm.js +14 -0
  7. package/dist/environment.js +1 -0
  8. package/dist/integrations/microsoftSqlServer.js +2 -5
  9. package/dist/integrations/mysql.js +3 -5
  10. package/dist/integrations/postgres.js +5 -7
  11. package/dist/integrations/redis.js +0 -7
  12. package/dist/integrations/rest.js +0 -4
  13. package/dist/migrations/functions/usageQuotas/syncApps.js +1 -1
  14. package/dist/migrations/functions/usageQuotas/syncRows.js +2 -1
  15. package/dist/package.json +14 -13
  16. package/dist/startup.js +27 -29
  17. package/dist/threads/automation.js +3 -14
  18. package/dist/tsconfig.build.tsbuildinfo +1 -1
  19. package/package.json +15 -14
  20. package/scripts/dev/manage.js +0 -2
  21. package/scripts/integrations/mssql/data/entrypoint.sh +0 -1
  22. package/scripts/integrations/mssql/data/setup.sql +17 -17
  23. package/scripts/integrations/mysql/init.sql +1 -1
  24. package/scripts/integrations/postgres/init.sql +0 -1
  25. package/scripts/likeCypress.ts +35 -0
  26. package/src/api/routes/index.ts +0 -2
  27. package/src/api/routes/tests/automation.spec.js +2 -5
  28. package/src/api/routes/tests/user.spec.js +13 -61
  29. package/src/app.ts +13 -2
  30. package/src/elasticApm.ts +10 -0
  31. package/src/environment.ts +1 -0
  32. package/src/integrations/microsoftSqlServer.ts +2 -5
  33. package/src/integrations/mysql.ts +3 -5
  34. package/src/integrations/postgres.ts +5 -7
  35. package/src/integrations/redis.ts +0 -8
  36. package/src/integrations/rest.ts +0 -3
  37. package/src/migrations/functions/usageQuotas/syncApps.ts +1 -1
  38. package/src/migrations/functions/usageQuotas/syncRows.ts +3 -2
  39. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +2 -2
  40. package/src/startup.ts +33 -34
  41. package/src/tests/jestEnv.ts +1 -0
  42. package/src/tests/jestSetup.ts +1 -0
  43. package/src/tests/logging.ts +34 -0
  44. package/src/threads/automation.ts +4 -16
  45. package/builder/assets/index.c176beea.js +0 -1776
  46. package/dist/api/controllers/ops.js +0 -40
  47. package/dist/api/routes/ops.js +0 -52
  48. package/src/api/controllers/ops.ts +0 -32
  49. package/src/api/routes/ops.ts +0 -30
@@ -8,8 +8,8 @@
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" />
9
9
  <link href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap"
10
10
  rel="stylesheet" />
11
- <script type="module" crossorigin src="/builder/assets/index.c176beea.js"></script>
12
- <link rel="stylesheet" href="/builder/assets/index.841e62d8.css">
11
+ <script type="module" crossorigin src="/builder/assets/index.f493a2b3.js"></script>
12
+ <link rel="stylesheet" href="/builder/assets/index.7f9a008b.css">
13
13
  </head>
14
14
 
15
15
  <body id="app">
@@ -31,7 +31,6 @@ const dev_1 = __importDefault(require("./dev"));
31
31
  const cloud_1 = __importDefault(require("./cloud"));
32
32
  const migrations_1 = __importDefault(require("./migrations"));
33
33
  const plugin_1 = __importDefault(require("./plugin"));
34
- const ops_1 = __importDefault(require("./ops"));
35
34
  const pro_1 = require("@budibase/pro");
36
35
  var static_1 = require("./static");
37
36
  Object.defineProperty(exports, "staticRoutes", { enumerable: true, get: function () { return __importDefault(static_1).default; } });
@@ -68,7 +67,6 @@ exports.mainRoutes = [
68
67
  row_1.default,
69
68
  migrations_1.default,
70
69
  plugin_1.default,
71
- ops_1.default,
72
70
  scheduleRoutes,
73
71
  environmentVariableRoutes,
74
72
  // these need to be handled last as they still use /api/:tableId
package/dist/app.js CHANGED
@@ -38,8 +38,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
38
38
  if (process.env.DD_APM_ENABLED) {
39
39
  require("./ddApm");
40
40
  }
41
+ if (process.env.ELASTIC_APM_ENABLED) {
42
+ require("./elasticApm");
43
+ }
41
44
  // need to load environment first
42
45
  const environment_1 = __importDefault(require("./environment"));
46
+ // enable APM if configured
47
+ if (process.env.ELASTIC_APM_ENABLED) {
48
+ const apm = require("elastic-apm-node").start({
49
+ serviceName: process.env.SERVICE,
50
+ environment: process.env.BUDIBASE_ENVIRONMENT,
51
+ });
52
+ }
43
53
  const db = __importStar(require("./db"));
44
54
  db.init();
45
55
  const koa_1 = __importDefault(require("koa"));
@@ -70,8 +80,7 @@ app.use((0, koa_body_1.default)({
70
80
  enableTypes: ["json", "form", "text"],
71
81
  parsedMethods: ["POST", "PUT", "PATCH", "DELETE"],
72
82
  }));
73
- app.use(backend_core_1.middleware.correlation);
74
- app.use(backend_core_1.middleware.pino);
83
+ app.use(backend_core_1.middleware.logging);
75
84
  app.use(userAgent);
76
85
  if (environment_1.default.isProd()) {
77
86
  environment_1.default._set("NODE_ENV", "production");
@@ -0,0 +1,14 @@
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 elastic_apm_node_1 = __importDefault(require("elastic-apm-node"));
7
+ // enable APM if configured
8
+ if (process.env.ELASTIC_APM_ENABLED) {
9
+ console.log("Starting elastic-apm-node");
10
+ elastic_apm_node_1.default.start({
11
+ serviceName: process.env.SERVICE,
12
+ environment: process.env.BUDIBASE_ENVIRONMENT,
13
+ });
14
+ }
@@ -54,6 +54,7 @@ const environment = {
54
54
  // minor
55
55
  SALT_ROUNDS: process.env.SALT_ROUNDS,
56
56
  LOGGER: process.env.LOGGER,
57
+ LOG_LEVEL: process.env.LOG_LEVEL,
57
58
  ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL,
58
59
  AUTOMATION_MAX_ITERATIONS: parseIntSafe(process.env.AUTOMATION_MAX_ITERATIONS) || 200,
59
60
  SENDGRID_API_KEY: process.env.SENDGRID_API_KEY,
@@ -206,11 +206,8 @@ class SqlServerIntegration extends sql_1.default {
206
206
  if (typeof name !== "string") {
207
207
  continue;
208
208
  }
209
- const hasDefault = def.COLUMN_DEFAULT;
210
- const isAuto = !!autoColumns.find(col => col === name);
211
- const required = !!requiredColumns.find(col => col === name);
212
- schema[name] = Object.assign(Object.assign({ autocolumn: isAuto, name: name, constraints: {
213
- presence: required && !isAuto && !hasDefault,
209
+ schema[name] = Object.assign(Object.assign({ autocolumn: !!autoColumns.find(col => col === name), name: name, constraints: {
210
+ presence: requiredColumns.find(col => col === name),
214
211
  } }, (0, utils_1.convertSqlType)(def.DATA_TYPE)), { externalType: def.DATA_TYPE });
215
212
  }
216
213
  tables[tableName] = {
@@ -186,14 +186,12 @@ class MySQLIntegration extends sql_1.default {
186
186
  if (column.Key === "PRI" && primaryKeys.indexOf(column.Key) === -1) {
187
187
  primaryKeys.push(columnName);
188
188
  }
189
- const hasDefault = column.Default != null;
189
+ const constraints = {
190
+ presence: column.Null !== "YES",
191
+ };
190
192
  const isAuto = typeof column.Extra === "string" &&
191
193
  (column.Extra === "auto_increment" ||
192
194
  column.Extra.toLowerCase().includes("generated"));
193
- const required = column.Null !== "YES";
194
- const constraints = {
195
- presence: required && !isAuto && !hasDefault,
196
- };
197
195
  schema[columnName] = Object.assign(Object.assign({ name: columnName, autocolumn: isAuto, constraints }, (0, utils_1.convertSqlType)(column.Type)), { externalType: column.Type });
198
196
  }
199
197
  if (!tables[tableName]) {
@@ -227,15 +227,13 @@ class PostgresIntegration extends sql_1.default {
227
227
  const identity = !!(column.identity_generation ||
228
228
  column.identity_start ||
229
229
  column.identity_increment);
230
- const hasDefault = column.column_default != null;
231
- const hasNextVal = typeof column.column_default === "string" &&
232
- column.column_default.startsWith("nextval");
233
- const isGenerated = column.is_generated && column.is_generated !== "NEVER";
234
- const isAuto = hasNextVal || identity || isGenerated;
235
- const required = column.is_nullable === "NO";
236
230
  const constraints = {
237
- presence: required && !hasDefault && !isGenerated,
231
+ presence: column.is_nullable === "NO",
238
232
  };
233
+ const hasDefault = typeof column.column_default === "string" &&
234
+ column.column_default.startsWith("nextval");
235
+ const isGenerated = column.is_generated && column.is_generated !== "NEVER";
236
+ const isAuto = hasDefault || identity || isGenerated;
239
237
  tables[tableName].schema[columnName] = Object.assign(Object.assign({ autocolumn: isAuto, name: columnName, constraints }, (0, utils_1.convertSqlType)(column.data_type)), { externalType: column.data_type });
240
238
  }
241
239
  const final = (0, utils_1.finaliseExternalTables)(tables, entities);
@@ -38,12 +38,6 @@ const SCHEMA = {
38
38
  type: "password",
39
39
  required: false,
40
40
  },
41
- db: {
42
- type: "number",
43
- required: false,
44
- display: "DB",
45
- default: 0,
46
- },
47
41
  },
48
42
  query: {
49
43
  create: {
@@ -96,7 +90,6 @@ class RedisIntegration {
96
90
  port: this.config.port,
97
91
  username: this.config.username,
98
92
  password: this.config.password,
99
- db: this.config.db,
100
93
  });
101
94
  }
102
95
  disconnect() {
@@ -166,10 +166,6 @@ class RestIntegration {
166
166
  }
167
167
  raw = rawXml;
168
168
  }
169
- else if (contentType.includes("application/pdf")) {
170
- data = yield response.arrayBuffer(); // Save PDF as ArrayBuffer
171
- raw = Buffer.from(data);
172
- }
173
169
  else {
174
170
  data = yield response.text();
175
171
  raw = data;
@@ -19,7 +19,7 @@ const run = () => __awaiter(void 0, void 0, void 0, function* () {
19
19
  const appCount = devApps ? devApps.length : 0;
20
20
  // sync app count
21
21
  const tenantId = backend_core_1.tenancy.getTenantId();
22
- console.log(`Syncing app count: ${appCount}`);
22
+ console.log(`[Tenant: ${tenantId}] Syncing app count: ${appCount}`);
23
23
  yield pro_1.quotas.setUsage(appCount, types_1.StaticQuotaName.APPS, types_1.QuotaUsageType.STATIC);
24
24
  });
25
25
  exports.run = run;
@@ -27,7 +27,8 @@ const run = () => __awaiter(void 0, void 0, void 0, function* () {
27
27
  rowCount += rows.length;
28
28
  });
29
29
  // sync row count
30
- console.log(`Syncing row count: ${rowCount}`);
30
+ const tenantId = backend_core_1.tenancy.getTenantId();
31
+ console.log(`[Tenant: ${tenantId}] Syncing row count: ${rowCount}`);
31
32
  yield pro_1.quotas.setUsagePerApp(counts, types_1.StaticQuotaName.ROWS, types_1.QuotaUsageType.STATIC);
32
33
  });
33
34
  exports.run = run;
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.5.5-alpha.3",
4
+ "version": "2.5.4",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -26,7 +26,6 @@
26
26
  "dev:stack:down": "node scripts/dev/manage.js down",
27
27
  "dev:stack:nuke": "node scripts/dev/manage.js nuke",
28
28
  "dev:builder": "yarn run dev:stack:up && nodemon",
29
- "dev:built": "yarn run dev:stack:up && yarn run run:docker",
30
29
  "specs": "ts-node specs/generate.ts && openapi-typescript specs/openapi.yaml --output src/definitions/openapi.ts",
31
30
  "initialise": "node scripts/initialise.js",
32
31
  "env:multi:enable": "node scripts/multiTenancy.js enable",
@@ -45,12 +44,12 @@
45
44
  "license": "GPL-3.0",
46
45
  "dependencies": {
47
46
  "@apidevtools/swagger-parser": "10.0.3",
48
- "@budibase/backend-core": "2.5.5-alpha.3",
49
- "@budibase/client": "2.5.5-alpha.3",
50
- "@budibase/pro": "2.5.5-alpha.2",
51
- "@budibase/shared-core": "2.5.5-alpha.3",
52
- "@budibase/string-templates": "2.5.5-alpha.3",
53
- "@budibase/types": "2.5.5-alpha.3",
47
+ "@budibase/backend-core": "^2.5.4",
48
+ "@budibase/client": "^2.5.4",
49
+ "@budibase/pro": "2.5.4",
50
+ "@budibase/shared-core": "^2.5.4",
51
+ "@budibase/string-templates": "^2.5.4",
52
+ "@budibase/types": "^2.5.4",
54
53
  "@bull-board/api": "3.7.0",
55
54
  "@bull-board/koa": "3.9.4",
56
55
  "@elastic/elasticsearch": "7.10.0",
@@ -86,6 +85,7 @@
86
85
  "koa-body": "4.2.0",
87
86
  "koa-compress": "4.0.1",
88
87
  "koa-connect": "2.1.0",
88
+ "koa-pino-logger": "3.0.0",
89
89
  "koa-send": "5.0.0",
90
90
  "koa-session": "5.12.0",
91
91
  "koa-static": "5.0.0",
@@ -99,6 +99,7 @@
99
99
  "node-fetch": "2.6.7",
100
100
  "open": "8.4.0",
101
101
  "pg": "8.5.1",
102
+ "pino-pretty": "4.0.0",
102
103
  "posthog-node": "1.3.0",
103
104
  "pouchdb": "7.3.0",
104
105
  "pouchdb-adapter-memory": "7.2.2",
@@ -115,10 +116,11 @@
115
116
  "to-json-schema": "0.2.5",
116
117
  "uuid": "3.3.2",
117
118
  "validate.js": "0.13.1",
118
- "vm2": "3.9.16",
119
+ "vm2": "^3.9.15",
119
120
  "worker-farm": "1.7.0",
120
- "xml2js": "0.5.0",
121
- "yargs": "13.2.4"
121
+ "xml2js": "0.4.23",
122
+ "yargs": "13.2.4",
123
+ "zlib": "1.0.5"
122
124
  },
123
125
  "devDependencies": {
124
126
  "@babel/core": "7.17.4",
@@ -147,7 +149,7 @@
147
149
  "@types/tar": "6.1.3",
148
150
  "@typescript-eslint/parser": "5.45.0",
149
151
  "apidoc": "0.50.4",
150
- "babel-jest": "29.5.0",
152
+ "babel-jest": "27.5.1",
151
153
  "copyfiles": "2.4.1",
152
154
  "docker-compose": "0.23.17",
153
155
  "eslint": "6.8.0",
@@ -155,7 +157,6 @@
155
157
  "is-wsl": "2.2.0",
156
158
  "jest": "29.5.0",
157
159
  "jest-openapi": "0.14.2",
158
- "jest-runner": "29.5.0",
159
160
  "jest-serial-runner": "^1.2.1",
160
161
  "nodemon": "2.0.15",
161
162
  "openapi-types": "9.3.1",
package/dist/startup.js CHANGED
@@ -50,9 +50,11 @@ const bullboard = __importStar(require("./automations/bullboard"));
50
50
  const pro = __importStar(require("@budibase/pro"));
51
51
  const api = __importStar(require("./api"));
52
52
  const sdk_1 = __importDefault(require("./sdk"));
53
+ const pino = require("koa-pino-logger");
53
54
  let STARTUP_RAN = false;
54
55
  function initRoutes(app) {
55
56
  return __awaiter(this, void 0, void 0, function* () {
57
+ app.use(pino(backend_core_1.logging.pinoSettings()));
56
58
  if (!environment_1.default.isTest()) {
57
59
  const plugin = yield bullboard.init();
58
60
  app.use(plugin);
@@ -77,10 +79,8 @@ function initPro() {
77
79
  });
78
80
  }
79
81
  function shutdown(server) {
80
- if (server) {
81
- server.close();
82
- server.destroy();
83
- }
82
+ server.close();
83
+ server.destroy();
84
84
  }
85
85
  function startup(app, server) {
86
86
  var _a;
@@ -104,33 +104,10 @@ function startup(app, server) {
104
104
  }
105
105
  catch (e) {
106
106
  backend_core_1.logging.logAlert("Error performing migrations. Exiting.", e);
107
- shutdown(server);
107
+ shutdown();
108
108
  }
109
109
  }
110
- // monitor plugin directory if required
111
- if (environment_1.default.SELF_HOSTED &&
112
- !environment_1.default.MULTI_TENANCY &&
113
- environment_1.default.PLUGINS_DIR &&
114
- fs_1.default.existsSync(environment_1.default.PLUGINS_DIR)) {
115
- (0, watch_1.watch)();
116
- }
117
- // check for version updates
118
- yield backend_core_1.installation.checkInstallVersion();
119
- // get the references to the queue promises, don't await as
120
- // they will never end, unless the processing stops
121
- let queuePromises = [];
122
- // configure events to use the pro audit log write
123
- // can't integrate directly into backend-core due to cyclic issues
124
- queuePromises.push(backend_core_1.events.processors.init(pro.sdk.auditLogs.write));
125
- queuePromises.push(automations.init());
126
- queuePromises.push(initPro());
127
- if (app) {
128
- // bring routes online as final step once everything ready
129
- yield initRoutes(app);
130
- }
131
110
  // check and create admin user if required
132
- // this must be run after the api has been initialised due to
133
- // the app user sync
134
111
  if (environment_1.default.SELF_HOSTED &&
135
112
  !environment_1.default.MULTI_TENANCY &&
136
113
  environment_1.default.BB_ADMIN_USER_EMAIL &&
@@ -148,10 +125,31 @@ function startup(app, server) {
148
125
  }
149
126
  catch (e) {
150
127
  backend_core_1.logging.logAlert("Error creating initial admin user. Exiting.", e);
151
- shutdown(server);
128
+ shutdown();
152
129
  }
153
130
  }
154
131
  }
132
+ // monitor plugin directory if required
133
+ if (environment_1.default.SELF_HOSTED &&
134
+ !environment_1.default.MULTI_TENANCY &&
135
+ environment_1.default.PLUGINS_DIR &&
136
+ fs_1.default.existsSync(environment_1.default.PLUGINS_DIR)) {
137
+ (0, watch_1.watch)();
138
+ }
139
+ // check for version updates
140
+ yield backend_core_1.installation.checkInstallVersion();
141
+ // get the references to the queue promises, don't await as
142
+ // they will never end, unless the processing stops
143
+ let queuePromises = [];
144
+ // configure events to use the pro audit log write
145
+ // can't integrate directly into backend-core due to cyclic issues
146
+ queuePromises.push(backend_core_1.events.processors.init(pro.sdk.auditLogs.write));
147
+ queuePromises.push(automations.init());
148
+ queuePromises.push(initPro());
149
+ if (app) {
150
+ // bring routes online as final step once everything ready
151
+ yield initRoutes(app);
152
+ }
155
153
  });
156
154
  }
157
155
  exports.startup = startup;
@@ -58,8 +58,8 @@ const CRON_STEP_ID = triggerInfo_1.definitions.CRON.stepId;
58
58
  const STOPPED_STATUS = { success: true, status: types_1.AutomationStatus.STOPPED };
59
59
  function getLoopIterations(loopStep, input) {
60
60
  const binding = automationUtils.typecastForLooping(loopStep, input);
61
- if (!binding) {
62
- return 0;
61
+ if (!loopStep || !binding) {
62
+ return 1;
63
63
  }
64
64
  if (Array.isArray(binding)) {
65
65
  return binding.length;
@@ -67,7 +67,7 @@ function getLoopIterations(loopStep, input) {
67
67
  if (typeof binding === "string") {
68
68
  return automationUtils.stringSplit(binding).length;
69
69
  }
70
- return 0;
70
+ return 1;
71
71
  }
72
72
  /**
73
73
  * The automation orchestrator is a class responsible for executing automations.
@@ -372,17 +372,6 @@ class Orchestrator {
372
372
  }
373
373
  }
374
374
  }
375
- if (loopStep && iterations === 0) {
376
- loopStep = undefined;
377
- this.executionOutput.steps.splice(loopStepNumber + 1, 0, {
378
- id: step.id,
379
- stepId: step.stepId,
380
- outputs: { status: types_1.AutomationStatus.NO_ITERATIONS, success: true },
381
- inputs: {},
382
- });
383
- this._context.steps.splice(loopStepNumber, 1);
384
- iterations = 1;
385
- }
386
375
  // Delete the step after the loop step as it's irrelevant, since information is included
387
376
  // in the loop step
388
377
  if (wasLoopStep && !loopStep) {