@budibase/backend-core 2.32.8 → 2.32.9

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/dist/index.js CHANGED
@@ -54894,6 +54894,7 @@ __export(helpers_exports, {
54894
54894
  isGoogleSheets: () => isGoogleSheets,
54895
54895
  isSQL: () => isSQL,
54896
54896
  schema: () => schema_exports,
54897
+ views: () => views_exports,
54897
54898
  withTimeout: () => withTimeout
54898
54899
  });
54899
54900
 
@@ -55044,6 +55045,7 @@ __export(schema_exports, {
55044
55045
  decodeNonAscii: () => decodeNonAscii,
55045
55046
  encodeNonAscii: () => encodeNonAscii,
55046
55047
  isDeprecatedSingleUserColumn: () => isDeprecatedSingleUserColumn,
55048
+ isNumeric: () => isNumeric,
55047
55049
  isRequired: () => isRequired
55048
55050
  });
55049
55051
  function isDeprecatedSingleUserColumn(schema) {
@@ -55065,9 +55067,38 @@ function decodeNonAscii(str) {
55065
55067
  (match, p1) => String.fromCharCode(parseInt(p1, 16))
55066
55068
  );
55067
55069
  }
55070
+ function isNumeric(field) {
55071
+ return field.type === "number" /* NUMBER */ || field.type === "bigint" /* BIGINT */;
55072
+ }
55068
55073
 
55069
- // ../shared-core/src/filters.ts
55074
+ // ../shared-core/src/helpers/views.ts
55075
+ var views_exports = {};
55076
+ __export(views_exports, {
55077
+ basicFields: () => basicFields,
55078
+ calculationFields: () => calculationFields,
55079
+ isBasicViewField: () => isBasicViewField,
55080
+ isCalculationField: () => isCalculationField,
55081
+ isCalculationView: () => isCalculationView
55082
+ });
55070
55083
  var import_lodash = require("lodash");
55084
+ function isCalculationField(field) {
55085
+ return "calculationType" in field;
55086
+ }
55087
+ function isBasicViewField(field) {
55088
+ return !isCalculationField(field);
55089
+ }
55090
+ function isCalculationView(view) {
55091
+ return Object.values(view.schema || {}).some(isCalculationField);
55092
+ }
55093
+ function calculationFields(view) {
55094
+ return (0, import_lodash.pickBy)(view.schema || {}, isCalculationField);
55095
+ }
55096
+ function basicFields(view) {
55097
+ return (0, import_lodash.pickBy)(view.schema || {}, (field) => !isCalculationField(field));
55098
+ }
55099
+
55100
+ // ../shared-core/src/filters.ts
55101
+ var import_lodash2 = require("lodash");
55071
55102
  var HBS_REGEX = /{{([^{].*?)}}/g;
55072
55103
  var LOGICAL_OPERATORS = Object.values(LogicalOperator);
55073
55104
  var SEARCH_OPERATORS = [
@@ -55136,7 +55167,7 @@ var NoEmptyFilterStrings = [
55136
55167
  ];
55137
55168
  function recurseLogicalOperators(filters, fn) {
55138
55169
  for (const logical of LOGICAL_OPERATORS) {
55139
- if (filters[logical]) {
55170
+ if (filters?.[logical]) {
55140
55171
  filters[logical].conditions = filters[logical].conditions.map(
55141
55172
  (condition) => fn(condition)
55142
55173
  );
@@ -55345,7 +55376,7 @@ var buildQuery = (filter) => {
55345
55376
  function fixupFilterArrays(filters) {
55346
55377
  for (const searchField of Object.values(ArrayOperator)) {
55347
55378
  const field = filters[searchField];
55348
- if (field == null || !(0, import_lodash.isPlainObject)(field)) {
55379
+ if (field == null || !(0, import_lodash2.isPlainObject)(field)) {
55349
55380
  continue;
55350
55381
  }
55351
55382
  for (const key of Object.keys(field)) {
@@ -55432,10 +55463,10 @@ function runQuery(docs, query) {
55432
55463
  if (docValue == null || docValue === "") {
55433
55464
  return false;
55434
55465
  }
55435
- if ((0, import_lodash.isPlainObject)(testValue.low) && (0, import_lodash.isEmpty)(testValue.low)) {
55466
+ if ((0, import_lodash2.isPlainObject)(testValue.low) && (0, import_lodash2.isEmpty)(testValue.low)) {
55436
55467
  testValue.low = void 0;
55437
55468
  }
55438
- if ((0, import_lodash.isPlainObject)(testValue.high) && (0, import_lodash.isEmpty)(testValue.high)) {
55469
+ if ((0, import_lodash2.isPlainObject)(testValue.high) && (0, import_lodash2.isEmpty)(testValue.high)) {
55439
55470
  testValue.high = void 0;
55440
55471
  }
55441
55472
  if (testValue.low == null && testValue.high == null) {
@@ -55687,6 +55718,7 @@ var utils_exports = {};
55687
55718
  __export(utils_exports, {
55688
55719
  filterValueToLabel: () => filterValueToLabel,
55689
55720
  hasSchema: () => hasSchema,
55721
+ isSupportedUserSearch: () => isSupportedUserSearch,
55690
55722
  parallelForeach: () => parallelForeach,
55691
55723
  trimOtherProps: () => trimOtherProps,
55692
55724
  unreachable: () => unreachable
@@ -55742,6 +55774,29 @@ function trimOtherProps(object, allowedProps) {
55742
55774
  );
55743
55775
  return result;
55744
55776
  }
55777
+ function isSupportedUserSearch(query) {
55778
+ const allowed = [
55779
+ { op: "string" /* STRING */, key: "email" },
55780
+ { op: "equal" /* EQUAL */, key: "_id" },
55781
+ { op: "oneOf" /* ONE_OF */, key: "_id" }
55782
+ ];
55783
+ for (let [key, operation] of Object.entries(query)) {
55784
+ if (typeof operation !== "object") {
55785
+ return false;
55786
+ }
55787
+ const fields = Object.keys(operation || {});
55788
+ if (fields.length === 0) {
55789
+ continue;
55790
+ }
55791
+ const allowedOperation = allowed.find(
55792
+ (allow) => allow.op === key && fields.length === 1 && fields[0] === allow.key
55793
+ );
55794
+ if (!allowedOperation) {
55795
+ return false;
55796
+ }
55797
+ }
55798
+ return true;
55799
+ }
55745
55800
 
55746
55801
  // ../shared-core/src/sdk/index.ts
55747
55802
  var sdk_exports = {};
@@ -56132,6 +56187,7 @@ __export(context_exports, {
56132
56187
  getProdAppDB: () => getProdAppDB,
56133
56188
  getProdAppId: () => getProdAppId,
56134
56189
  getScimDBName: () => getScimDBName,
56190
+ getTableForView: () => getTableForView,
56135
56191
  getTenantIDFromAppID: () => getTenantIDFromAppID,
56136
56192
  getTenantId: () => getTenantId,
56137
56193
  identity: () => identity_exports,
@@ -56139,7 +56195,8 @@ __export(context_exports, {
56139
56195
  isScim: () => isScim,
56140
56196
  isTenancyEnabled: () => isTenancyEnabled,
56141
56197
  isTenantIdSet: () => isTenantIdSet,
56142
- setFeatureFlags: () => setFeatureFlags
56198
+ setFeatureFlags: () => setFeatureFlags,
56199
+ setTableForView: () => setTableForView
56143
56200
  });
56144
56201
 
56145
56202
  // src/context/identity.ts
@@ -56193,7 +56250,7 @@ function getAccountUserId(account) {
56193
56250
 
56194
56251
  // src/environment.ts
56195
56252
  var import_fs = require("fs");
56196
- var import_lodash2 = require("lodash");
56253
+ var import_lodash3 = require("lodash");
56197
56254
  function isTest() {
56198
56255
  return isJest();
56199
56256
  }
@@ -56361,7 +56418,7 @@ var environment = {
56361
56418
  OPENAI_API_KEY: process.env.OPENAI_API_KEY
56362
56419
  };
56363
56420
  function setEnv(newEnvVars) {
56364
- const oldEnv = (0, import_lodash2.cloneDeep)(environment);
56421
+ const oldEnv = (0, import_lodash3.cloneDeep)(environment);
56365
56422
  let key;
56366
56423
  for (key in newEnvVars) {
56367
56424
  environment._set(key, newEnvVars[key]);
@@ -56913,6 +56970,7 @@ __export(db_exports, {
56913
56970
  isProdAppID: () => isProdAppID,
56914
56971
  isSameAppID: () => isSameAppID,
56915
56972
  isTableId: () => isTableId,
56973
+ isViewId: () => isViewId,
56916
56974
  paginatedSearch: () => paginatedSearch,
56917
56975
  pagination: () => pagination,
56918
56976
  prefixRoleID: () => prefixRoleID,
@@ -58531,6 +58589,7 @@ __export(docIds_exports, {
58531
58589
  isDatasourceId: () => isDatasourceId,
58532
58590
  isGlobalUserID: () => isGlobalUserID,
58533
58591
  isTableId: () => isTableId,
58592
+ isViewId: () => isViewId,
58534
58593
  prefixRoleID: () => prefixRoleID
58535
58594
  });
58536
58595
 
@@ -58616,8 +58675,11 @@ function getQueryIndex(viewName) {
58616
58675
  var isTableId = (id) => {
58617
58676
  return !!id && (id.startsWith(`${"ta" /* TABLE */}${SEPARATOR}`) || id.startsWith(`${"datasource_plus" /* DATASOURCE_PLUS */}${SEPARATOR}`));
58618
58677
  };
58678
+ function isViewId(id) {
58679
+ return !!id && id.startsWith(`${"view" /* VIEW */}${SEPARATOR}`);
58680
+ }
58619
58681
  var isDatasourceId = (id) => {
58620
- return id && id.startsWith(`${"datasource" /* DATASOURCE */}${SEPARATOR}`);
58682
+ return !!id && id.startsWith(`${"datasource" /* DATASOURCE */}${SEPARATOR}`);
58621
58683
  };
58622
58684
  function getWorkspaceParams(id = "", otherProps = {}) {
58623
58685
  return {
@@ -60378,7 +60440,7 @@ var flags = new FlagSet({
60378
60440
  AUTOMATION_BRANCHING: Flag.boolean(environment_default.isDev()),
60379
60441
  SQS: Flag.boolean(environment_default.isDev()),
60380
60442
  ["AI_CUSTOM_CONFIGS" /* AI_CUSTOM_CONFIGS */]: Flag.boolean(environment_default.isDev()),
60381
- ["ENRICHED_RELATIONSHIPS" /* ENRICHED_RELATIONSHIPS */]: Flag.boolean(false)
60443
+ ["ENRICHED_RELATIONSHIPS" /* ENRICHED_RELATIONSHIPS */]: Flag.boolean(environment_default.isDev())
60382
60444
  });
60383
60445
 
60384
60446
  // src/db/couch/DatabaseImpl.ts
@@ -61042,6 +61104,21 @@ function setFeatureFlags(key, value) {
61042
61104
  context.featureFlagCache ??= {};
61043
61105
  context.featureFlagCache[key] = value;
61044
61106
  }
61107
+ function getTableForView(viewId) {
61108
+ const context = getCurrentContext();
61109
+ if (!context) {
61110
+ return;
61111
+ }
61112
+ return context.viewToTableCache?.[viewId];
61113
+ }
61114
+ function setTableForView(viewId, table) {
61115
+ const context = getCurrentContext();
61116
+ if (!context) {
61117
+ return;
61118
+ }
61119
+ context.viewToTableCache ??= {};
61120
+ context.viewToTableCache[viewId] = table;
61121
+ }
61045
61122
 
61046
61123
  // src/cache/base/index.ts
61047
61124
  function generateTenantKey(key) {
@@ -61635,7 +61712,6 @@ __export(users_exports3, {
61635
61712
  isBuilder: () => isBuilder2,
61636
61713
  isCreator: () => isCreator2,
61637
61714
  isGlobalBuilder: () => isGlobalBuilder2,
61638
- isSupportedUserSearch: () => isSupportedUserSearch,
61639
61715
  paginatedUsers: () => paginatedUsers,
61640
61716
  removeAppBuilder: () => removeAppBuilder,
61641
61717
  removePortalUserPermissions: () => removePortalUserPermissions,
@@ -65509,29 +65585,6 @@ function removeUserPassword(users) {
65509
65585
  }
65510
65586
  return users;
65511
65587
  }
65512
- function isSupportedUserSearch(query) {
65513
- const allowed = [
65514
- { op: "string" /* STRING */, key: "email" },
65515
- { op: "equal" /* EQUAL */, key: "_id" },
65516
- { op: "oneOf" /* ONE_OF */, key: "_id" }
65517
- ];
65518
- for (let [key, operation] of Object.entries(query)) {
65519
- if (typeof operation !== "object") {
65520
- return false;
65521
- }
65522
- const fields = Object.keys(operation || {});
65523
- if (fields.length === 0) {
65524
- continue;
65525
- }
65526
- const allowedOperation = allowed.find(
65527
- (allow) => allow.op === key && fields.length === 1 && fields[0] === allow.key
65528
- );
65529
- if (!allowedOperation) {
65530
- return false;
65531
- }
65532
- }
65533
- return true;
65534
- }
65535
65588
  async function bulkGetGlobalUsersById(userIds, opts) {
65536
65589
  const db = getGlobalDB();
65537
65590
  let users = (await db.allDocs({
@@ -68095,7 +68148,7 @@ var SqlTableQueryBuilder = class {
68095
68148
  var sqlTable_default = SqlTableQueryBuilder;
68096
68149
 
68097
68150
  // src/sql/sql.ts
68098
- var import_lodash3 = require("lodash");
68151
+ var import_lodash4 = require("lodash");
68099
68152
  function getBaseLimit() {
68100
68153
  const envLimit = environment_default.SQL_MAX_ROWS ? parseInt(environment_default.SQL_MAX_ROWS) : null;
68101
68154
  return envLimit || 5e3;
@@ -68284,7 +68337,7 @@ var InternalBuilder = class {
68284
68337
  return body2;
68285
68338
  }
68286
68339
  parseFilters(filters) {
68287
- filters = (0, import_lodash3.cloneDeep)(filters);
68340
+ filters = (0, import_lodash4.cloneDeep)(filters);
68288
68341
  for (const op of Object.values(BasicOperator)) {
68289
68342
  const filter = filters[op];
68290
68343
  if (!filter) {
@@ -68706,8 +68759,36 @@ var InternalBuilder = class {
68706
68759
  }
68707
68760
  return query.countDistinct(`${aliased}.${primary[0]} as total`);
68708
68761
  }
68762
+ addAggregations(query, aggregations) {
68763
+ const fields = this.query.resource?.fields || [];
68764
+ if (fields.length > 0) {
68765
+ query = query.groupBy(fields.map((field) => `${this.table.name}.${field}`));
68766
+ }
68767
+ for (const aggregation of aggregations) {
68768
+ const op = aggregation.calculationType;
68769
+ const field = `${this.table.name}.${aggregation.field} as ${aggregation.name}`;
68770
+ switch (op) {
68771
+ case "count" /* COUNT */:
68772
+ query = query.count(field);
68773
+ break;
68774
+ case "sum" /* SUM */:
68775
+ query = query.sum(field);
68776
+ break;
68777
+ case "avg" /* AVG */:
68778
+ query = query.avg(field);
68779
+ break;
68780
+ case "min" /* MIN */:
68781
+ query = query.min(field);
68782
+ break;
68783
+ case "max" /* MAX */:
68784
+ query = query.max(field);
68785
+ break;
68786
+ }
68787
+ }
68788
+ return query;
68789
+ }
68709
68790
  addSorting(query) {
68710
- let { sort: sort2 } = this.query;
68791
+ let { sort: sort2, resource } = this.query;
68711
68792
  const primaryKey = this.table.primary;
68712
68793
  const tableName = getTableName(this.table);
68713
68794
  const aliases = this.query.tableAliases;
@@ -68732,7 +68813,8 @@ var InternalBuilder = class {
68732
68813
  }
68733
68814
  }
68734
68815
  }
68735
- if (!sort2 || sort2[primaryKey[0]] === void 0) {
68816
+ const hasAggregations = (resource?.aggregations?.length ?? 0) > 0;
68817
+ if (!hasAggregations && (!sort2 || sort2[primaryKey[0]] === void 0)) {
68736
68818
  query = query.orderBy(`${aliased}.${primaryKey[0]}`);
68737
68819
  }
68738
68820
  return query;
@@ -69006,7 +69088,14 @@ var InternalBuilder = class {
69006
69088
  query = query.offset(foundOffset);
69007
69089
  }
69008
69090
  }
69009
- query = !counting ? query.select(this.generateSelectStatement()) : this.addDistinctCount(query);
69091
+ const aggregations = this.query.resource?.aggregations || [];
69092
+ if (counting) {
69093
+ query = this.addDistinctCount(query);
69094
+ } else if (aggregations.length > 0) {
69095
+ query = this.addAggregations(query, aggregations);
69096
+ } else {
69097
+ query = query.select(this.generateSelectStatement());
69098
+ }
69010
69099
  if (!counting) {
69011
69100
  query = this.addSorting(query);
69012
69101
  }