@saltcorn/data 0.8.8-beta.1 → 0.8.8-beta.3

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 (50) hide show
  1. package/dist/base-plugin/actions.js +2 -2
  2. package/dist/base-plugin/actions.js.map +1 -1
  3. package/dist/base-plugin/fieldviews.js +1 -1
  4. package/dist/base-plugin/fieldviews.js.map +1 -1
  5. package/dist/base-plugin/index.d.ts +87 -87
  6. package/dist/base-plugin/types.d.ts.map +1 -1
  7. package/dist/base-plugin/types.js +1 -0
  8. package/dist/base-plugin/types.js.map +1 -1
  9. package/dist/base-plugin/viewtemplates/edit.d.ts.map +1 -1
  10. package/dist/base-plugin/viewtemplates/edit.js +14 -1
  11. package/dist/base-plugin/viewtemplates/edit.js.map +1 -1
  12. package/dist/base-plugin/viewtemplates/filter.js +1 -1
  13. package/dist/base-plugin/viewtemplates/filter.js.map +1 -1
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/migrations/202308211648.d.ts +2 -0
  19. package/dist/migrations/202308211648.d.ts.map +1 -0
  20. package/dist/migrations/202308211648.js +4 -0
  21. package/dist/migrations/202308211648.js.map +1 -0
  22. package/dist/models/expression.d.ts +1 -1
  23. package/dist/models/expression.d.ts.map +1 -1
  24. package/dist/models/expression.js +17 -3
  25. package/dist/models/expression.js.map +1 -1
  26. package/dist/models/index.d.ts +2 -2
  27. package/dist/models/index.d.ts.map +1 -1
  28. package/dist/models/page.d.ts.map +1 -1
  29. package/dist/models/page.js +7 -1
  30. package/dist/models/page.js.map +1 -1
  31. package/dist/models/plugin.js +1 -1
  32. package/dist/models/plugin.js.map +1 -1
  33. package/dist/models/table.d.ts +85 -6
  34. package/dist/models/table.d.ts.map +1 -1
  35. package/dist/models/table.js +216 -24
  36. package/dist/models/table.js.map +1 -1
  37. package/dist/models/table_constraints.d.ts.map +1 -1
  38. package/dist/models/table_constraints.js +19 -4
  39. package/dist/models/table_constraints.js.map +1 -1
  40. package/dist/models/view.js +1 -1
  41. package/dist/models/view.js.map +1 -1
  42. package/dist/plugin-helper.d.ts.map +1 -1
  43. package/dist/plugin-helper.js +35 -29
  44. package/dist/plugin-helper.js.map +1 -1
  45. package/dist/tests/table.test.js +22 -0
  46. package/dist/tests/table.test.js.map +1 -1
  47. package/dist/utils.d.ts.map +1 -1
  48. package/dist/utils.js +3 -1
  49. package/dist/utils.js.map +1 -1
  50. package/package.json +7 -7
@@ -42,10 +42,10 @@ const csvtojson_1 = __importDefault(require("csvtojson"));
42
42
  const moment_1 = __importDefault(require("moment"));
43
43
  const fs_1 = require("fs");
44
44
  const promises_1 = require("fs/promises");
45
- const utils_1 = __importDefault(require("../utils"));
46
45
  //import { num_between } from "@saltcorn/types/generators";
47
46
  //import { devNull } from "os";
48
- const { prefixFieldsInWhere, InvalidConfiguration, InvalidAdminAction, satisfies, structuredClone, getLines, mergeIntoWhere, stringToJSON, } = utils_1.default;
47
+ const utils_1 = __importDefault(require("../utils"));
48
+ const { prefixFieldsInWhere, InvalidConfiguration, InvalidAdminAction, satisfies, structuredClone, getLines, mergeIntoWhere, stringToJSON, isNode, } = utils_1.default;
49
49
  const tags_1 = __importDefault(require("@saltcorn/markup/tags"));
50
50
  const { text } = tags_1.default;
51
51
  /**
@@ -111,6 +111,7 @@ class Table {
111
111
  this.ownership_field_id = o.ownership_field_id;
112
112
  this.ownership_formula = o.ownership_formula;
113
113
  this.versioned = !!o.versioned;
114
+ this.has_sync_info = !!o.has_sync_info;
114
115
  this.is_user_group = !!o.is_user_group;
115
116
  this.external = false;
116
117
  this.description = o.description;
@@ -233,6 +234,11 @@ class Table {
233
234
  }
234
235
  return [...dbs, ...externals];
235
236
  }
237
+ /**
238
+ * Get Models
239
+ * tbd why this function in this file - needs to models
240
+ * @param opts
241
+ */
236
242
  async get_models(opts) {
237
243
  const Model = require("./model");
238
244
  if (typeof opts === "string")
@@ -281,6 +287,10 @@ class Table {
281
287
  return user && user.id && row && `${row.id}` === `${user.id}`;
282
288
  return typeof field_name === "string" && row[field_name] === user.id;
283
289
  }
290
+ /**
291
+ * get Ownership options
292
+ * user interface...
293
+ */
284
294
  async ownership_options() {
285
295
  const fields = this.fields;
286
296
  //start with userfields
@@ -391,6 +401,9 @@ class Table {
391
401
  }
392
402
  return opts;
393
403
  }
404
+ /**
405
+ * get sanitized name of table
406
+ */
394
407
  get santized_name() {
395
408
  return (0, internal_1.sqlsanitize)(this.name);
396
409
  }
@@ -461,8 +474,10 @@ class Table {
461
474
  }
462
475
  /**
463
476
  * Drop current table
477
+ * @param only_forget boolean - if true that only
464
478
  * @returns {Promise<void>}
465
479
  */
480
+ // tbd check all other tables related to table description
466
481
  async delete(only_forget = false) {
467
482
  const schema = db_1.default.getTenantSchemaPrefix();
468
483
  const is_sqlite = db_1.default.isSQLite;
@@ -470,12 +485,16 @@ class Table {
470
485
  const client = is_sqlite ? db_1.default : await db_1.default.getClient();
471
486
  await client.query(`BEGIN`);
472
487
  try {
488
+ // drop table
473
489
  if (!only_forget)
474
490
  await client.query(`drop table if exists ${schema}"${(0, internal_1.sqlsanitize)(this.name)}"`);
491
+ // delete fields
475
492
  await client.query(`delete FROM ${schema}_sc_fields WHERE table_id = $1`, [this.id]);
493
+ // delete table description
476
494
  await client.query(`delete FROM ${schema}_sc_tables WHERE id = $1`, [
477
495
  this.id,
478
496
  ]);
497
+ // delete versioned table
479
498
  if (this.versioned)
480
499
  await client.query(`drop table if exists ${schema}"${(0, internal_1.sqlsanitize)(this.name)}__history"`);
481
500
  await client.query(`COMMIT`);
@@ -491,12 +510,15 @@ class Table {
491
510
  await require("../db/state").getState().refresh_tables();
492
511
  }
493
512
  /***
494
- * get Table SQL Name
513
+ * Get Table SQL Name
495
514
  * @type {string}
496
515
  */
497
516
  get sql_name() {
498
517
  return `${db_1.default.getTenantSchemaPrefix()}"${(0, internal_1.sqlsanitize)(this.name)}"`;
499
518
  }
519
+ /**
520
+ * Reset Sequence
521
+ */
500
522
  async resetSequence() {
501
523
  const fields = this.fields;
502
524
  const pk = fields.find((f) => f.primary_key);
@@ -508,6 +530,13 @@ class Table {
508
530
  pk.type.name === "Integer")
509
531
  await db_1.default.reset_sequence(this.name);
510
532
  }
533
+ /**
534
+ * update Where with Ownership
535
+ * @param where
536
+ * @param fields
537
+ * @param user
538
+ * @param forRead
539
+ */
511
540
  updateWhereWithOwnership(where, fields, user, forRead) {
512
541
  const role = user?.role_id;
513
542
  const min_role = forRead ? this.min_role_read : this.min_role_write;
@@ -524,13 +553,31 @@ class Table {
524
553
  });
525
554
  }
526
555
  }
556
+ async addDeleteSyncInfo(ids, timestamp) {
557
+ if (ids.length > 0) {
558
+ const schema = db_1.default.getTenantSchemaPrefix();
559
+ const pkName = this.pk_name;
560
+ if (isNode()) {
561
+ await db_1.default.query(`delete from ${schema}${db_1.default.sqlsanitize(this.name)}_sync_info where ref in (
562
+ ${ids.map((row) => row[pkName]).join(",")})`);
563
+ await db_1.default.query(`insert into ${schema}${db_1.default.sqlsanitize(this.name)}_sync_info values ${ids
564
+ .map((row) => `(${row[pkName]}, date_trunc('milliseconds', to_timestamp( ${timestamp.valueOf() / 1000.0} ) ), true)`)
565
+ .join(",")}`);
566
+ }
567
+ else {
568
+ await db_1.default.query(`update ${db_1.default.sqlsanitize(this.name)}_sync_info
569
+ set deleted = true, modified_local = true
570
+ where ref in (${ids.map((row) => row[pkName]).join(",")})`);
571
+ }
572
+ }
573
+ }
527
574
  /**
528
575
  * Delete rows from table
529
576
  * @param where - condition
530
577
  * @param user - optional user, if null then no authorization will be checked
531
578
  * @returns
532
579
  */
533
- async deleteRows(where, user) {
580
+ async deleteRows(where, user, noTrigger) {
534
581
  // get triggers on delete
535
582
  const triggers = await trigger_1.default.getTableTriggers("Delete", this);
536
583
  const fields = this.fields;
@@ -548,7 +595,7 @@ class Table {
548
595
  }
549
596
  const deleteFileFields = fields.filter((f) => f.type === "File" && f.attributes?.also_delete_file);
550
597
  const deleteFiles = [];
551
- if (triggers.length > 0 || deleteFileFields.length > 0) {
598
+ if ((triggers.length > 0 || deleteFileFields.length > 0) && !noTrigger) {
552
599
  const File = require("./file");
553
600
  if (!rows)
554
601
  rows = await this.getJoinedRows({
@@ -569,12 +616,28 @@ class Table {
569
616
  }
570
617
  }
571
618
  }
572
- if (rows)
619
+ if (rows) {
573
620
  await db_1.default.deleteWhere(this.name, {
574
621
  [this.pk_name]: { in: rows.map((r) => r[this.pk_name]) },
575
622
  });
576
- else
623
+ if (this.has_sync_info) {
624
+ const dbTime = await db_1.default.time();
625
+ const ids = rows.map((r) => r[this.pk_name || "id"]);
626
+ await this.addDeleteSyncInfo(ids, dbTime);
627
+ }
628
+ }
629
+ else {
630
+ const delIds = this.has_sync_info
631
+ ? await db_1.default.select(this.name, where, {
632
+ fields: [this.pk_name],
633
+ })
634
+ : null;
577
635
  await db_1.default.deleteWhere(this.name, where);
636
+ if (this.has_sync_info) {
637
+ const dbTime = await db_1.default.time();
638
+ await this.addDeleteSyncInfo(delIds, dbTime);
639
+ }
640
+ }
578
641
  if (fields.find((f) => f.primary_key))
579
642
  await this.resetSequence();
580
643
  for (const file of deleteFiles) {
@@ -658,7 +721,7 @@ class Table {
658
721
  else
659
722
  return []; //no ownership
660
723
  }
661
- return apply_calculated_fields(rows.map((r) => this.readFromDB(r)), this.fields);
724
+ return apply_calculated_fields(rows.map((r) => this.readFromDB(r)), this.fields, !!selopts.ignore_errors);
662
725
  }
663
726
  /**
664
727
  * Count amount of rows in db table
@@ -685,6 +748,9 @@ class Table {
685
748
  return res.rows.map((r) => r[fieldnm]);
686
749
  }
687
750
  }
751
+ /**
752
+ *
753
+ */
688
754
  storedExpressionJoinFields() {
689
755
  let freeVars = new Set([]);
690
756
  for (const f of this.fields)
@@ -697,14 +763,14 @@ class Table {
697
763
  }
698
764
  /**
699
765
  * Update row
700
- * @param v_in - colums with values to update
766
+ * @param v_in - columns with values to update
701
767
  * @param id - id value
702
768
  * @param _userid - user id
703
769
  * @param noTrigger
704
770
  * @param resultCollector
705
771
  * @returns
706
772
  */
707
- async updateRow(v_in, id, user, noTrigger, resultCollector, restore_of_version) {
773
+ async updateRow(v_in, id, user, noTrigger, resultCollector, restore_of_version, syncTimestamp) {
708
774
  let existing;
709
775
  let v = { ...v_in };
710
776
  const fields = this.fields;
@@ -827,6 +893,13 @@ class Table {
827
893
  });
828
894
  }
829
895
  await db_1.default.update(this.name, v, id, { pk_name });
896
+ if (this.has_sync_info) {
897
+ const oldInfo = await this.latestSyncInfo(id);
898
+ if (oldInfo && !oldInfo.deleted)
899
+ await this.updateSyncInfo(id, oldInfo.last_modified, syncTimestamp);
900
+ else
901
+ await this.insertSyncInfo(id, syncTimestamp);
902
+ }
830
903
  const newRow = { ...existing, ...v, [pk_name]: id };
831
904
  if (!noTrigger) {
832
905
  const trigPromise = trigger_1.default.runTableTriggers("Update", this, newRow, resultCollector, role === 100 ? undefined : user, { old_row: existing, updated_fields: v_in });
@@ -834,6 +907,39 @@ class Table {
834
907
  await trigPromise;
835
908
  }
836
909
  }
910
+ async latestSyncInfo(id) {
911
+ const rows = await this.latestSyncInfos([id]);
912
+ return rows?.length === 1 ? rows[0] : null;
913
+ }
914
+ async latestSyncInfos(ids) {
915
+ const schema = db_1.default.getTenantSchemaPrefix();
916
+ const dbResult = await db_1.default.query(`select max(last_modified) "last_modified", ref
917
+ from ${schema}"${db_1.default.sqlsanitize(this.name)}_sync_info"
918
+ group by ref having ref in (${ids.join(",")})`);
919
+ return dbResult.rows;
920
+ }
921
+ async insertSyncInfo(id, syncTimestamp) {
922
+ const schema = db_1.default.getTenantSchemaPrefix();
923
+ if (isNode()) {
924
+ await db_1.default.query(`insert into ${schema}"${db_1.default.sqlsanitize(this.name)}_sync_info" values(${id},
925
+ date_trunc('milliseconds', to_timestamp(${(syncTimestamp ? syncTimestamp : await db_1.default.time()).valueOf() / 1000.0})))`);
926
+ }
927
+ else {
928
+ await db_1.default.query(`insert into "${db_1.default.sqlsanitize(this.name)}_sync_info"
929
+ (ref, modified_local, deleted)
930
+ values(${id}, true, false)`);
931
+ }
932
+ }
933
+ async updateSyncInfo(id, oldLastModified, syncTimestamp) {
934
+ const schema = db_1.default.getTenantSchemaPrefix();
935
+ if (!db_1.default.isSQLite) {
936
+ await db_1.default.query(`update ${schema}"${db_1.default.sqlsanitize(this.name)}_sync_info" set last_modified=date_trunc('milliseconds', to_timestamp(${(syncTimestamp ? syncTimestamp : await db_1.default.time()).valueOf() / 1000.0})) where ref=${id} and last_modified = to_timestamp(${oldLastModified.valueOf() / 1000.0})`);
937
+ }
938
+ else {
939
+ await db_1.default.query(`update "${db_1.default.sqlsanitize(this.name)}_sync_info" set modified_local = true
940
+ where ref = ${id} and last_modified = ${oldLastModified.valueOf()}`);
941
+ }
942
+ }
837
943
  /**
838
944
  * Try to Update row
839
945
  * @param v
@@ -876,7 +982,16 @@ class Table {
876
982
  }
877
983
  return pkField;
878
984
  }
879
- check_table_constraints(row) {
985
+ /**
986
+ * Check table constraints
987
+ * @param row
988
+ */
989
+ check_table_constraints(row0) {
990
+ const row = { ...row0 };
991
+ this.fields.forEach((f) => {
992
+ if (typeof row[f.name] === "undefined")
993
+ row[f.name] = null;
994
+ });
880
995
  const fmls = this.constraints
881
996
  .filter((c) => c.type === "Formula")
882
997
  .map((c) => c.configuration);
@@ -886,6 +1001,11 @@ class Table {
886
1001
  }
887
1002
  return undefined;
888
1003
  }
1004
+ /**
1005
+ *
1006
+ * @param row
1007
+ * @param user
1008
+ */
889
1009
  check_field_write_role(row, user) {
890
1010
  for (const field of this.fields) {
891
1011
  if (typeof row[field.name] !== "undefined" &&
@@ -902,7 +1022,7 @@ class Table {
902
1022
  * @param resultCollector
903
1023
  * @returns {Promise<*>}
904
1024
  */
905
- async insertRow(v_in, user, resultCollector) {
1025
+ async insertRow(v_in, user, resultCollector, noTrigger, syncTimestamp) {
906
1026
  const fields = this.fields;
907
1027
  const pk_name = this.pk_name;
908
1028
  const joinFields = this.storedExpressionJoinFields();
@@ -980,9 +1100,23 @@ class Table {
980
1100
  _userid: user?.id,
981
1101
  _time: new Date(),
982
1102
  });
983
- const trigPromise = trigger_1.default.runTableTriggers("Insert", this, { [pk_name]: id, ...v }, resultCollector, user);
984
- if (resultCollector)
985
- await trigPromise;
1103
+ if (this.has_sync_info) {
1104
+ if (isNode()) {
1105
+ const schemaPrefix = db_1.default.getTenantSchemaPrefix();
1106
+ await db_1.default.query(`insert into ${schemaPrefix}${db_1.default.sqlsanitize(this.name)}_sync_info
1107
+ values(${id}, date_trunc('milliseconds', to_timestamp(${(syncTimestamp ? syncTimestamp : await db_1.default.time()).valueOf() / 1000.0})))`);
1108
+ }
1109
+ else {
1110
+ await db_1.default.query(`insert into ${db_1.default.sqlsanitize(this.name)}_sync_info
1111
+ (last_modified, ref, modified_local, deleted)
1112
+ values(NULL, ${id}, true, false)`);
1113
+ }
1114
+ }
1115
+ if (!noTrigger) {
1116
+ const trigPromise = trigger_1.default.runTableTriggers("Insert", this, { [pk_name]: id, ...v }, resultCollector, user);
1117
+ if (resultCollector)
1118
+ await trigPromise;
1119
+ }
986
1120
  return id;
987
1121
  }
988
1122
  /**
@@ -1005,6 +1139,10 @@ class Table {
1005
1139
  return { error: this.normalise_error_message(e.message) };
1006
1140
  }
1007
1141
  }
1142
+ /**
1143
+ *
1144
+ * @param msg
1145
+ */
1008
1146
  normalise_error_message(msg) {
1009
1147
  let fieldnm = "";
1010
1148
  if (msg.toLowerCase().includes("unique constraint")) {
@@ -1118,6 +1256,28 @@ class Table {
1118
1256
  ,PRIMARY KEY("${pk}", _version)
1119
1257
  );`);
1120
1258
  }
1259
+ async create_sync_info_table() {
1260
+ const schemaPrefix = db_1.default.getTenantSchemaPrefix();
1261
+ const fields = this.fields;
1262
+ const pk = fields.find((f) => f.primary_key)?.name;
1263
+ if (!pk) {
1264
+ throw new Error("Unable to find a field with a primary key.");
1265
+ }
1266
+ await db_1.default.query(`create table ${schemaPrefix}${(0, internal_1.sqlsanitize)(this.name)}_sync_info (ref integer, last_modified timestamp, deleted boolean default false)`);
1267
+ await db_1.default.query(`create index ${(0, internal_1.sqlsanitize)(this.name)}_sync_info_ref_index on ${schemaPrefix}${(0, internal_1.sqlsanitize)(this.name)}_sync_info(ref)`);
1268
+ await db_1.default.query(`create index ${(0, internal_1.sqlsanitize)(this.name)}_sync_info_lm_index on ${schemaPrefix}${(0, internal_1.sqlsanitize)(this.name)}_sync_info(last_modified)`);
1269
+ }
1270
+ async drop_sync_table() {
1271
+ const schemaPrefix = db_1.default.getTenantSchemaPrefix();
1272
+ await db_1.default.query(`
1273
+ drop table ${schemaPrefix}"${(0, internal_1.sqlsanitize)(this.name)}_sync_info";`);
1274
+ }
1275
+ /**
1276
+ * Restore Row Version
1277
+ * @param id
1278
+ * @param version
1279
+ * @param user
1280
+ */
1121
1281
  async restore_row_version(id, version, user) {
1122
1282
  const row = await db_1.default.selectOne(`${db_1.default.sqlsanitize(this.name)}__history`, {
1123
1283
  id,
@@ -1131,28 +1291,38 @@ class Table {
1131
1291
  //console.log("restore_row_version", r);
1132
1292
  await this.updateRow(r, id, user, false, undefined, version);
1133
1293
  }
1294
+ /**
1295
+ * Undo row chnages
1296
+ * @param id
1297
+ * @param user
1298
+ */
1134
1299
  async undo_row_changes(id, user) {
1135
- const current_verion_row = await db_1.default.selectMaybeOne(`${(0, internal_1.sqlsanitize)(this.name)}__history`, { id }, { orderBy: "_version", orderDesc: true, limit: 1 });
1300
+ const current_version_row = await db_1.default.selectMaybeOne(`${(0, internal_1.sqlsanitize)(this.name)}__history`, { id }, { orderBy: "_version", orderDesc: true, limit: 1 });
1136
1301
  //get max that is not a restore
1137
1302
  const last_non_restore = await db_1.default.selectMaybeOne(`${(0, internal_1.sqlsanitize)(this.name)}__history`, {
1138
1303
  id,
1139
1304
  _version: {
1140
- lt: current_verion_row._restore_of_version
1141
- ? current_verion_row._restore_of_version
1142
- : current_verion_row._version,
1305
+ lt: current_version_row._restore_of_version
1306
+ ? current_version_row._restore_of_version
1307
+ : current_version_row._version,
1143
1308
  },
1144
1309
  }, { orderBy: "_version", orderDesc: true, limit: 1 });
1145
1310
  if (last_non_restore) {
1146
1311
  await this.restore_row_version(id, last_non_restore._version, user);
1147
1312
  }
1148
1313
  }
1314
+ /**
1315
+ * Redo row changes
1316
+ * @param id
1317
+ * @param user
1318
+ */
1149
1319
  async redo_row_changes(id, user) {
1150
- const current_verion_row = await db_1.default.selectMaybeOne(`${(0, internal_1.sqlsanitize)(this.name)}__history`, { id }, { orderBy: "_version", orderDesc: true, limit: 1 });
1151
- if (current_verion_row._restore_of_version) {
1320
+ const current_version_row = await db_1.default.selectMaybeOne(`${(0, internal_1.sqlsanitize)(this.name)}__history`, { id }, { orderBy: "_version", orderDesc: true, limit: 1 });
1321
+ if (current_version_row._restore_of_version) {
1152
1322
  const next_version = await db_1.default.selectMaybeOne(`${(0, internal_1.sqlsanitize)(this.name)}__history`, {
1153
1323
  id,
1154
1324
  _version: {
1155
- gt: current_verion_row._restore_of_version,
1325
+ gt: current_version_row._restore_of_version,
1156
1326
  },
1157
1327
  }, { orderBy: "_version", limit: 1 });
1158
1328
  if (next_version) {
@@ -1228,6 +1398,12 @@ class Table {
1228
1398
  else if (!new_table.versioned && existing.versioned) {
1229
1399
  await new_table.drop_history_table();
1230
1400
  }
1401
+ if (new_table.has_sync_info && !existing.has_sync_info) {
1402
+ await this.create_sync_info_table();
1403
+ }
1404
+ else if (!new_table.has_sync_info && existing.has_sync_info) {
1405
+ await new_table.drop_sync_table();
1406
+ }
1231
1407
  Object.assign(this, new_table_rec);
1232
1408
  }
1233
1409
  }
@@ -1334,6 +1510,10 @@ class Table {
1334
1510
  await require("../db/state").getState().refresh_tables();
1335
1511
  return parse_res;
1336
1512
  }
1513
+ /**
1514
+ *
1515
+ * @param state
1516
+ */
1337
1517
  read_state_strict(state) {
1338
1518
  let errorString = "";
1339
1519
  this.fields.forEach((f) => {
@@ -2057,7 +2237,7 @@ class Table {
2057
2237
  const res = await db_1.default.query(sql, values);
2058
2238
  if (res.length === 0)
2059
2239
  return res; // check
2060
- let calcRow = apply_calculated_fields(res.rows, fields);
2240
+ let calcRow = apply_calculated_fields(res.rows, fields, !!opts?.ignore_errors);
2061
2241
  //rename joinfields
2062
2242
  if (Object.values(joinFields || {}).some((jf) => jf.rename_object)) {
2063
2243
  let f = (x) => x;
@@ -2127,6 +2307,9 @@ class Table {
2127
2307
  }
2128
2308
  return calcRow;
2129
2309
  }
2310
+ /**
2311
+ *
2312
+ */
2130
2313
  async slug_options() {
2131
2314
  const fields = this.fields;
2132
2315
  const unique_fields = fields.filter((f) => f.is_unique);
@@ -2151,18 +2334,27 @@ class Table {
2151
2334
  opts.unshift({ label: "", steps: [] });
2152
2335
  return opts;
2153
2336
  }
2337
+ /**
2338
+ *
2339
+ */
2154
2340
  static async allSlugOptions() {
2155
- const tables = await Table.find({});
2341
+ const tables = await Table.find({}, { cached: true });
2156
2342
  const options = {};
2157
2343
  for (const table of tables) {
2158
2344
  options[table.name] = await table.slug_options();
2159
2345
  }
2160
2346
  return options;
2161
2347
  }
2348
+ /**
2349
+ *
2350
+ */
2162
2351
  async getTags() {
2163
2352
  const Tag = (await Promise.resolve().then(() => __importStar(require("./tag")))).default;
2164
2353
  return await Tag.findWithEntries({ table_id: this.id });
2165
2354
  }
2355
+ /**
2356
+ *
2357
+ */
2166
2358
  async getForeignTables() {
2167
2359
  const result = new Array();
2168
2360
  if (this.fields) {