@saltcorn/data 0.9.4-beta.2 → 0.9.4-beta.21

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 (129) hide show
  1. package/dist/base-plugin/actions.d.ts +156 -67
  2. package/dist/base-plugin/actions.d.ts.map +1 -1
  3. package/dist/base-plugin/actions.js +151 -27
  4. package/dist/base-plugin/actions.js.map +1 -1
  5. package/dist/base-plugin/fieldviews.d.ts.map +1 -1
  6. package/dist/base-plugin/fieldviews.js +27 -10
  7. package/dist/base-plugin/fieldviews.js.map +1 -1
  8. package/dist/base-plugin/fileviews.d.ts +13 -0
  9. package/dist/base-plugin/fileviews.js +42 -2
  10. package/dist/base-plugin/fileviews.js.map +1 -1
  11. package/dist/base-plugin/index.d.ts +5 -2
  12. package/dist/base-plugin/index.d.ts.map +1 -1
  13. package/dist/base-plugin/types.d.ts.map +1 -1
  14. package/dist/base-plugin/types.js +25 -7
  15. package/dist/base-plugin/types.js.map +1 -1
  16. package/dist/base-plugin/viewtemplates/edit.d.ts +2 -0
  17. package/dist/base-plugin/viewtemplates/edit.d.ts.map +1 -1
  18. package/dist/base-plugin/viewtemplates/edit.js +194 -58
  19. package/dist/base-plugin/viewtemplates/edit.js.map +1 -1
  20. package/dist/base-plugin/viewtemplates/filter.d.ts.map +1 -1
  21. package/dist/base-plugin/viewtemplates/filter.js +88 -8
  22. package/dist/base-plugin/viewtemplates/filter.js.map +1 -1
  23. package/dist/base-plugin/viewtemplates/list.d.ts +3 -2
  24. package/dist/base-plugin/viewtemplates/list.d.ts.map +1 -1
  25. package/dist/base-plugin/viewtemplates/list.js +276 -41
  26. package/dist/base-plugin/viewtemplates/list.js.map +1 -1
  27. package/dist/base-plugin/viewtemplates/show.d.ts.map +1 -1
  28. package/dist/base-plugin/viewtemplates/show.js +130 -64
  29. package/dist/base-plugin/viewtemplates/show.js.map +1 -1
  30. package/dist/base-plugin/viewtemplates/viewable_fields.d.ts +4 -3
  31. package/dist/base-plugin/viewtemplates/viewable_fields.d.ts.map +1 -1
  32. package/dist/base-plugin/viewtemplates/viewable_fields.js +160 -47
  33. package/dist/base-plugin/viewtemplates/viewable_fields.js.map +1 -1
  34. package/dist/db/fixtures.d.ts.map +1 -1
  35. package/dist/db/fixtures.js +196 -30
  36. package/dist/db/fixtures.js.map +1 -1
  37. package/dist/db/state.d.ts +5 -0
  38. package/dist/db/state.d.ts.map +1 -1
  39. package/dist/db/state.js +20 -0
  40. package/dist/db/state.js.map +1 -1
  41. package/dist/migrate.d.ts +1 -0
  42. package/dist/migrate.d.ts.map +1 -1
  43. package/dist/migrate.js +6 -3
  44. package/dist/migrate.js.map +1 -1
  45. package/dist/migrations/202402071125.d.ts +2 -0
  46. package/dist/migrations/202402071125.d.ts.map +1 -0
  47. package/dist/migrations/202402071125.js +4 -0
  48. package/dist/migrations/202402071125.js.map +1 -0
  49. package/dist/models/config.d.ts.map +1 -1
  50. package/dist/models/config.js +33 -0
  51. package/dist/models/config.js.map +1 -1
  52. package/dist/models/email.d.ts.map +1 -1
  53. package/dist/models/email.js +6 -2
  54. package/dist/models/email.js.map +1 -1
  55. package/dist/models/expression.d.ts +2 -0
  56. package/dist/models/expression.d.ts.map +1 -1
  57. package/dist/models/expression.js +9 -0
  58. package/dist/models/expression.js.map +1 -1
  59. package/dist/models/field.d.ts +1 -1
  60. package/dist/models/field.d.ts.map +1 -1
  61. package/dist/models/field.js +4 -4
  62. package/dist/models/field.js.map +1 -1
  63. package/dist/models/file.d.ts +2 -0
  64. package/dist/models/file.d.ts.map +1 -1
  65. package/dist/models/file.js +9 -0
  66. package/dist/models/file.js.map +1 -1
  67. package/dist/models/internal/query.d.ts +6 -0
  68. package/dist/models/internal/query.d.ts.map +1 -0
  69. package/dist/models/internal/query.js +77 -0
  70. package/dist/models/internal/query.js.map +1 -0
  71. package/dist/models/page.d.ts.map +1 -1
  72. package/dist/models/page.js +4 -0
  73. package/dist/models/page.js.map +1 -1
  74. package/dist/models/page_group.d.ts +1 -0
  75. package/dist/models/page_group.d.ts.map +1 -1
  76. package/dist/models/page_group.js +1 -0
  77. package/dist/models/page_group.js.map +1 -1
  78. package/dist/models/table.d.ts +18 -4
  79. package/dist/models/table.d.ts.map +1 -1
  80. package/dist/models/table.js +78 -50
  81. package/dist/models/table.js.map +1 -1
  82. package/dist/models/trigger.d.ts +3 -3
  83. package/dist/models/trigger.d.ts.map +1 -1
  84. package/dist/models/trigger.js +69 -7
  85. package/dist/models/trigger.js.map +1 -1
  86. package/dist/models/user.d.ts.map +1 -1
  87. package/dist/models/user.js +5 -4
  88. package/dist/models/user.js.map +1 -1
  89. package/dist/models/view.d.ts +1 -0
  90. package/dist/models/view.d.ts.map +1 -1
  91. package/dist/models/view.js +6 -0
  92. package/dist/models/view.js.map +1 -1
  93. package/dist/plugin-helper.d.ts +8 -20
  94. package/dist/plugin-helper.d.ts.map +1 -1
  95. package/dist/plugin-helper.js +108 -76
  96. package/dist/plugin-helper.js.map +1 -1
  97. package/dist/tests/actions.test.js +143 -2
  98. package/dist/tests/actions.test.js.map +1 -1
  99. package/dist/tests/auth.test.js +101 -1
  100. package/dist/tests/auth.test.js.map +1 -1
  101. package/dist/tests/auxtest.test.js +4 -0
  102. package/dist/tests/auxtest.test.js.map +1 -1
  103. package/dist/tests/calc.test.js +11 -1
  104. package/dist/tests/calc.test.js.map +1 -1
  105. package/dist/tests/edit.test.js +394 -0
  106. package/dist/tests/edit.test.js.map +1 -1
  107. package/dist/tests/filter.test.d.ts +2 -0
  108. package/dist/tests/filter.test.d.ts.map +1 -0
  109. package/dist/tests/filter.test.js +438 -0
  110. package/dist/tests/filter.test.js.map +1 -0
  111. package/dist/tests/list.test.d.ts +2 -0
  112. package/dist/tests/list.test.d.ts.map +1 -0
  113. package/dist/tests/list.test.js +735 -0
  114. package/dist/tests/list.test.js.map +1 -0
  115. package/dist/tests/show.test.d.ts +2 -0
  116. package/dist/tests/show.test.d.ts.map +1 -0
  117. package/dist/tests/show.test.js +325 -0
  118. package/dist/tests/show.test.js.map +1 -0
  119. package/dist/tests/table.test.js +184 -56
  120. package/dist/tests/table.test.js.map +1 -1
  121. package/dist/tests/table_history.test.js +51 -0
  122. package/dist/tests/table_history.test.js.map +1 -1
  123. package/dist/tests/view.test.js +21 -1
  124. package/dist/tests/view.test.js.map +1 -1
  125. package/dist/utils.d.ts +4 -17
  126. package/dist/utils.d.ts.map +1 -1
  127. package/dist/utils.js +33 -32
  128. package/dist/utils.js.map +1 -1
  129. package/package.json +8 -7
@@ -12,8 +12,9 @@ const Tag = require("./models/tag");
12
12
  const { getState } = require("./db/state");
13
13
  const db = require("./db");
14
14
  const { button, a, text, i } = require("@saltcorn/markup/tags");
15
- const { applyAsync, InvalidConfiguration, parseRelationPath, buildRelationPath, mergeActionResults, } = require("./utils");
16
- const { jsexprToWhere, freeVariables, add_free_variables_to_joinfields, eval_expression, } = require("./models/expression");
15
+ const { Relation, RelationType, ViewDisplayType, parseRelationPath, buildRelationPath, } = require("@saltcorn/common-code");
16
+ const { applyAsync, InvalidConfiguration, mergeActionResults, } = require("./utils");
17
+ const { jsexprToWhere, freeVariables, add_free_variables_to_joinfields, eval_expression, freeVariablesInInterpolation, } = require("./models/expression");
17
18
  const { traverseSync } = require("./models/layout");
18
19
  const { isNode } = require("./utils");
19
20
  /**
@@ -635,6 +636,7 @@ const field_picker_fields = async ({ table, viewname, req, has_click_to_edit, ha
635
636
  ];
636
637
  const triggers = Trigger.find({
637
638
  when_trigger: { or: ["API call", "Never"] },
639
+ table_id: null,
638
640
  });
639
641
  triggers.forEach((tr) => {
640
642
  actions.push(tr.name);
@@ -1288,7 +1290,7 @@ const get_onetoone_views = async (table, viewname) => {
1288
1290
  * @throws {InvalidConfiguration}
1289
1291
  * @returns {object}
1290
1292
  */
1291
- const picked_fields_to_query = (columns, fields, layout) => {
1293
+ const picked_fields_to_query = (columns, fields, layout, req) => {
1292
1294
  let joinFields = {};
1293
1295
  let aggregations = {};
1294
1296
  let freeVars = new Set(); // for join fields
@@ -1339,8 +1341,11 @@ const picked_fields_to_query = (columns, fields, layout) => {
1339
1341
  freeVars = new Set([...freeVars, ...freeVariables(column.formula)]);
1340
1342
  }
1341
1343
  else if (column.type === "ViewLink") {
1342
- if (column.view_label_formula)
1343
- freeVars = new Set([...freeVars, ...freeVariables(column.view_label)]);
1344
+ if (column.view_label_formula || column.isFormula?.label)
1345
+ freeVars = new Set([
1346
+ ...freeVars,
1347
+ ...freeVariables(column.view_label || column.label),
1348
+ ]);
1344
1349
  if (column.extra_state_fml)
1345
1350
  freeVars = new Set([
1346
1351
  ...freeVars,
@@ -1392,7 +1397,9 @@ const picked_fields_to_query = (columns, fields, layout) => {
1392
1397
  aggregations[targetNm] = {
1393
1398
  table,
1394
1399
  ref: fld,
1395
- where: column.aggwhere ? jsexprToWhere(column.aggwhere) : undefined,
1400
+ where: column.aggwhere
1401
+ ? jsexprToWhere(column.aggwhere, req ? { user: req.user } : {})
1402
+ : undefined,
1396
1403
  field,
1397
1404
  aggregate: column.stat,
1398
1405
  through,
@@ -1408,6 +1415,8 @@ const picked_fields_to_query = (columns, fields, layout) => {
1408
1415
  else if (column.type === "Action" && column.action_label_formula) {
1409
1416
  freeVars = new Set([...freeVars, ...freeVariables(column.action_label)]);
1410
1417
  }
1418
+ if (column.showif)
1419
+ freeVars = new Set([...freeVars, ...freeVariables(column.showif)]);
1411
1420
  });
1412
1421
  if (layout) {
1413
1422
  traverseSync(layout, {
@@ -1443,14 +1452,26 @@ const picked_fields_to_query = (columns, fields, layout) => {
1443
1452
  if (v?.isFormula?.url && typeof v.url === "string")
1444
1453
  freeVars = new Set([...freeVars, ...freeVariables(v.url)]);
1445
1454
  },
1455
+ tabs(v) {
1456
+ (v.titles || []).forEach((t) => {
1457
+ if (typeof t === "string")
1458
+ freeVars = new Set([
1459
+ ...freeVars,
1460
+ ...freeVariablesInInterpolation(t),
1461
+ ]);
1462
+ });
1463
+ (v.showif || []).forEach((t) => {
1464
+ freeVars = new Set([...freeVars, ...freeVariablesInInterpolation(t)]);
1465
+ });
1466
+ },
1446
1467
  blank(v) {
1447
1468
  if (v?.isFormula?.text && typeof v.contents === "string")
1448
1469
  freeVars = new Set([...freeVars, ...freeVariables(v.contents)]);
1449
1470
  if (v.isHTML)
1450
- ((v.contents || "").match(/\{\{([^#].+?)\}\}/g) || []).forEach((s) => {
1451
- const s1 = s.replace("{{", "").replace("}}", "").trim();
1452
- freeVars = new Set([...freeVars, ...freeVariables(s1)]);
1453
- });
1471
+ freeVars = new Set([
1472
+ ...freeVars,
1473
+ ...freeVariablesInInterpolation(v.contents),
1474
+ ]);
1454
1475
  },
1455
1476
  container(v) {
1456
1477
  if (v.showIfFormula)
@@ -1464,6 +1485,12 @@ const picked_fields_to_query = (columns, fields, layout) => {
1464
1485
  },
1465
1486
  });
1466
1487
  }
1488
+ if (layout?.besides && layout?.list_columns) {
1489
+ layout?.besides.forEach((s) => {
1490
+ if (s.showif)
1491
+ freeVars = new Set([...freeVars, ...freeVariables(s.showif)]);
1492
+ });
1493
+ }
1467
1494
  add_free_variables_to_joinfields(freeVars, joinFields, fields);
1468
1495
  return { joinFields, aggregations };
1469
1496
  };
@@ -1977,7 +2004,7 @@ const readState = (state, fields, req) => {
1977
2004
  else if (typeof current === "object") {
1978
2005
  //ignore
1979
2006
  }
1980
- else if (f.type.read)
2007
+ else if (f.type?.read)
1981
2008
  state[f.name] = f.type.read(current);
1982
2009
  else if (typeof current === "string" && current.startsWith("Preset:")) {
1983
2010
  const pname = current.replace("Preset:", "");
@@ -2048,7 +2075,7 @@ const readStateStrict = (state, fields) => {
2048
2075
  const json_list_to_external_table = (get_json_list, fields0) => {
2049
2076
  const fields = fields0.map((f) => f.constructor.name === Object.name ? new Field(f) : f);
2050
2077
  const getRows = async (where = {}, selopts = {}) => {
2051
- let data_in = await get_json_list({ where, ...selopts });
2078
+ let data_in = await get_json_list(where, selopts);
2052
2079
  const restricts = Object.entries(where);
2053
2080
  const sat = (x) => ([k, v]) => {
2054
2081
  if (Array.isArray(v))
@@ -2060,7 +2087,7 @@ const json_list_to_external_table = (get_json_list, fields0) => {
2060
2087
  else if (v?.ilike)
2061
2088
  return (x[k] || "").includes(v.ilike);
2062
2089
  else
2063
- return x[k] === v;
2090
+ return x[k] == v;
2064
2091
  };
2065
2092
  const data_filtered = restricts.length === 0
2066
2093
  ? data_in
@@ -2077,6 +2104,7 @@ const json_list_to_external_table = (get_json_list, fields0) => {
2077
2104
  return data_filtered;
2078
2105
  };
2079
2106
  const tbl = {
2107
+ pk_name: fields.find((f) => f.primary_key)?.name,
2080
2108
  getFields() {
2081
2109
  return fields;
2082
2110
  },
@@ -2100,8 +2128,13 @@ const json_list_to_external_table = (get_json_list, fields0) => {
2100
2128
  const { where, ...rest } = opts;
2101
2129
  return getRows(where || {}, rest || {});
2102
2130
  },
2131
+ async getJoinedRow(opts = {}) {
2132
+ const { where, ...rest } = opts;
2133
+ const rows = await getRows(where || {}, rest || {});
2134
+ return rows.length > 0 ? rows[0] : null;
2135
+ },
2103
2136
  async countRows(where, opts) {
2104
- let data_in = await get_json_list({ ...where, ...opts });
2137
+ let data_in = await get_json_list(where, opts);
2105
2138
  return data_in.length;
2106
2139
  },
2107
2140
  get_child_relations() {
@@ -2122,6 +2155,7 @@ const json_list_to_external_table = (get_json_list, fields0) => {
2122
2155
  slug_options() {
2123
2156
  return [];
2124
2157
  },
2158
+ enable_fkey_constraints() { },
2125
2159
  ownership_options() {
2126
2160
  return [];
2127
2161
  },
@@ -2157,44 +2191,69 @@ const run_action_column = async ({ col, req, ...rest }) => {
2157
2191
  const run_action_step = async (action_name, colcfg) => {
2158
2192
  let state_action = getState().actions[action_name];
2159
2193
  let configuration;
2160
- if (state_action)
2194
+ let goRun;
2195
+ if (state_action) {
2161
2196
  configuration = colcfg;
2197
+ goRun = () => state_action.run({
2198
+ configuration,
2199
+ user: req.user,
2200
+ req,
2201
+ ...rest,
2202
+ });
2203
+ }
2162
2204
  else {
2163
2205
  const trigger = await Trigger.findOne({ name: action_name });
2164
- if (trigger) {
2206
+ if (trigger?.action === "Multi-step action") {
2207
+ goRun = () => trigger.runWithoutRow({ req, ...rest });
2208
+ }
2209
+ else if (trigger) {
2165
2210
  state_action = getState().actions[trigger.action];
2166
- configuration = trigger.configuration;
2211
+ goRun = () => state_action.run({
2212
+ configuration: trigger.configuration,
2213
+ user: req.user,
2214
+ req,
2215
+ ...rest,
2216
+ });
2167
2217
  }
2168
2218
  }
2169
- if (!state_action)
2219
+ if (!goRun)
2170
2220
  throw new Error("Runnable action not found: " + text(action_name));
2171
- return await state_action.run({
2172
- configuration,
2173
- user: req.user,
2174
- req,
2175
- ...rest,
2176
- });
2221
+ return await goRun();
2177
2222
  };
2178
2223
  if (col.action_name === "Multi-step action") {
2179
- const result = {};
2180
- for (let i = 0; i < col.step_action_names.length; i++) {
2224
+ let result = {};
2225
+ let step_count = 0;
2226
+ let MAX_STEPS = 200;
2227
+ for (let i = 0; i < col.step_action_names.length && step_count < MAX_STEPS; i++) {
2228
+ step_count += 1;
2181
2229
  const action_name = col.step_action_names?.[i];
2182
2230
  if (!action_name)
2183
2231
  continue;
2184
2232
  const only_if = col.step_only_ifs?.[i];
2185
2233
  const config = col.configuration.steps?.[i] || {};
2186
2234
  if (only_if && rest.row) {
2187
- if (!eval_expression(only_if, rest.row, rest.req?.user))
2235
+ if (!eval_expression(only_if, rest.row, req?.user))
2188
2236
  continue;
2189
2237
  }
2190
2238
  const stepres = await run_action_step(action_name, config);
2239
+ if (stepres?.goto_step) {
2240
+ i = +stepres.goto_step - 2;
2241
+ delete stepres.goto_step;
2242
+ }
2243
+ if (stepres?.clear_return_values)
2244
+ result = {};
2245
+ if (stepres?.set_fields && rest?.row) {
2246
+ Object.entries(stepres?.set_fields).forEach(([k, v]) => {
2247
+ rest.row[k] = v;
2248
+ });
2249
+ }
2191
2250
  try {
2192
2251
  mergeActionResults(result, stepres);
2193
2252
  }
2194
2253
  catch (error) {
2195
2254
  console.error(error);
2196
2255
  }
2197
- if (result.error)
2256
+ if (result.error || result.halt_steps)
2198
2257
  break;
2199
2258
  }
2200
2259
  return result;
@@ -2202,11 +2261,6 @@ const run_action_column = async ({ col, req, ...rest }) => {
2202
2261
  else
2203
2262
  return await run_action_step(col.action_name, col.configuration);
2204
2263
  };
2205
- const ViewDisplayType = {
2206
- ROW_REQUIRED: "ROW_REQUIRED",
2207
- NO_ROW_LIMIT: "NO_ROW_LIMIT",
2208
- INVALID: "INVALID",
2209
- };
2210
2264
  const displayType = (stateFields) => stateFields.every((sf) => !sf.required)
2211
2265
  ? ViewDisplayType.NO_ROW_LIMIT
2212
2266
  : stateFields.some((sf) => sf.name === "id")
@@ -2240,54 +2294,32 @@ const build_schema_data = async () => {
2240
2294
  return { views, tables };
2241
2295
  };
2242
2296
  /**
2243
- * tries to match a type to a relation
2244
- * if it's not ChildList, ParentShow, Own, or Independent then RelationPath is returned
2245
- * @param {View} subView
2246
- * @param {string[]} path
2247
- * @param {Table} srcTable
2248
- * @returns ChildList, ParentShow, Own, Independent or RelationPath
2249
- */
2250
- const relationTypeFromPath = (subview, path, srcTable) => {
2251
- if (path.length === 1 && path[0].inboundKey)
2252
- return "ChildList"; // works for OneToOneShow as well
2253
- else if (path.length === 2 && path.every((p) => p.inboundKey))
2254
- return "ChildList";
2255
- else if (path.length === 1 && path[0].fkey)
2256
- return "ParentShow";
2257
- else if (path.length === 0)
2258
- return subview.table_id === srcTable.id ? "Own" : "Independent";
2259
- else
2260
- return "RelationPath";
2261
- };
2262
- /**
2263
- * creates a state object from a relation path
2264
- * @param {View} subview
2265
- * @param {string} relation
2266
- * @param {string[]} pathArr
2267
- * @param {Function} getRowVal
2268
- * @param {Table} srcTbl
2297
+ *
2298
+ * @param {Relation} relation
2299
+ * @param {function} getRowVal
2269
2300
  */
2270
- const pathToState = (subview, relation, pathArr, getRowVal, srcTbl) => {
2271
- const subTbl = Table.findOne({ id: subview.table_id });
2272
- const pkName = subTbl.pk_name;
2273
- switch (relationTypeFromPath(subview, pathArr, srcTbl)) {
2274
- case "ChildList":
2275
- return pathArr.length === 1
2276
- ? {
2277
- [pathArr[0].inboundKey]: getRowVal(pkName), // works for OneToOneShow as well
2278
- }
2301
+ const pathToState = (relation, getRowVal) => {
2302
+ const targetTbl = Table.findOne({ name: relation.targetTblName });
2303
+ const pkName = targetTbl.pk_name;
2304
+ const path = relation.path;
2305
+ switch (relation.type) {
2306
+ case RelationType.CHILD_LIST:
2307
+ case RelationType.ONE_TO_ONE_SHOW:
2308
+ return path.length === 1
2309
+ ? { [path[0].inboundKey]: getRowVal(pkName) }
2279
2310
  : {
2280
- [`${pathArr[1].table}.${pathArr[1].inboundKey}.${pathArr[0].table}.${pathArr[0].inboundKey}`]: getRowVal(pkName),
2311
+ [`${path[1].table}.${path[1].inboundKey}.${path[0].table}.${path[0].inboundKey}`]: getRowVal(pkName),
2281
2312
  };
2282
- case "ParentShow":
2283
- return { id: getRowVal(pathArr[0].fkey) };
2284
- case "Own":
2313
+ case RelationType.PARENT_SHOW:
2314
+ return { id: getRowVal(path[0].fkey) };
2315
+ case RelationType.OWN:
2285
2316
  return { [pkName]: getRowVal(pkName) };
2286
- case "Independent":
2317
+ case RelationType.INDEPENDENT:
2318
+ case RelationType.NONE:
2287
2319
  return {};
2288
- case "RelationPath":
2320
+ case RelationType.RELATION_PATH:
2289
2321
  return {
2290
- [relation]: getRowVal(pathArr[0].fkey ? pathArr[0].fkey : pkName) || "NULL",
2322
+ [relation.relationString]: getRowVal(path[0].fkey ? path[0].fkey : pkName) || "NULL",
2291
2323
  };
2292
2324
  }
2293
2325
  };
@@ -2316,7 +2348,7 @@ module.exports = {
2316
2348
  get_inbound_self_relation_opts,
2317
2349
  get_many_to_many_relation_opts,
2318
2350
  build_schema_data,
2319
- relationTypeFromPath,
2320
2351
  pathToState,
2352
+ displayType,
2321
2353
  };
2322
2354
  //# sourceMappingURL=plugin-helper.js.map