@saltcorn/data 0.6.1-beta.0 → 0.6.1

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 (60) hide show
  1. package/base-plugin/actions.js +172 -1
  2. package/base-plugin/fieldviews.js +63 -0
  3. package/base-plugin/fileviews.js +41 -0
  4. package/base-plugin/index.js +35 -0
  5. package/base-plugin/types.js +345 -9
  6. package/base-plugin/viewtemplates/edit.js +107 -0
  7. package/base-plugin/viewtemplates/feed.js +46 -0
  8. package/base-plugin/viewtemplates/filter.js +43 -0
  9. package/base-plugin/viewtemplates/list.js +73 -1
  10. package/base-plugin/viewtemplates/listshowlist.js +54 -3
  11. package/base-plugin/viewtemplates/room.js +100 -0
  12. package/base-plugin/viewtemplates/show.js +86 -0
  13. package/base-plugin/viewtemplates/viewable_fields.js +124 -0
  14. package/contracts.js +58 -0
  15. package/db/connect.js +13 -5
  16. package/db/db.test.js +0 -154
  17. package/db/fixtures.js +13 -1
  18. package/db/index.js +42 -3
  19. package/db/reset_schema.js +11 -0
  20. package/db/state.js +105 -36
  21. package/index.js +13 -0
  22. package/migrate.js +4 -1
  23. package/models/backup.js +78 -0
  24. package/models/config.js +113 -22
  25. package/models/crash.js +44 -0
  26. package/models/discovery.js +13 -11
  27. package/models/email.js +17 -0
  28. package/models/eventlog.js +51 -0
  29. package/models/expression.js +49 -1
  30. package/models/field.js +88 -9
  31. package/models/fieldrepeat.js +33 -0
  32. package/models/file.js +23 -4
  33. package/models/form.js +34 -0
  34. package/models/index.js +42 -0
  35. package/models/layout.js +33 -0
  36. package/models/library.js +44 -0
  37. package/models/pack.js +88 -0
  38. package/models/page.js +13 -3
  39. package/models/plugin.js +9 -2
  40. package/models/random.js +36 -0
  41. package/models/role.js +36 -0
  42. package/models/scheduler.js +28 -0
  43. package/models/table.js +34 -15
  44. package/models/table_constraints.js +44 -0
  45. package/models/tenant.js +46 -9
  46. package/models/trigger.js +24 -11
  47. package/models/user.js +33 -8
  48. package/models/view.js +89 -8
  49. package/models/workflow.js +31 -0
  50. package/package.json +7 -5
  51. package/plugin-helper.js +102 -44
  52. package/plugin-testing.js +4 -0
  53. package/tests/exact_views.test.js +5 -5
  54. package/utils.js +4 -0
  55. package/db/internal.js +0 -229
  56. package/db/multi-tenant.js +0 -24
  57. package/db/pg.js +0 -374
  58. package/db/single-tenant.js +0 -8
  59. package/db/sqlite.js +0 -280
  60. package/db/tenants.js +0 -6
package/models/view.js CHANGED
@@ -1,6 +1,8 @@
1
1
  /**
2
- *
3
2
  * View Data Access Layer
3
+ * @category saltcorn-data
4
+ * @module models/view
5
+ * @subcategory models
4
6
  */
5
7
 
6
8
  const db = require("../db");
@@ -21,8 +23,13 @@ const { renderForm } = require("@saltcorn/markup");
21
23
 
22
24
  /**
23
25
  * View Class
26
+ * @category saltcorn-data
24
27
  */
25
28
  class View {
29
+ /**
30
+ * View constructor
31
+ * @param {object} o
32
+ */
26
33
  constructor(o) {
27
34
  this.name = o.name;
28
35
  this.id = o.id;
@@ -46,6 +53,11 @@ class View {
46
53
  this.default_render_page = o.default_render_page;
47
54
  contract.class(this);
48
55
  }
56
+
57
+ /**
58
+ * @param {object} where
59
+ * @returns {View}
60
+ */
49
61
  static findOne(where) {
50
62
  const { getState } = require("../db/state");
51
63
  const v = getState().views.find(
@@ -61,20 +73,22 @@ class View {
61
73
  }
62
74
 
63
75
  /**
64
- *
65
76
  * @param where
66
77
  * @param selectopts
67
- * @returns {Promise<*>}
78
+ * @returns {Promise<View[]>}
68
79
  */
69
80
  static async find(where, selectopts = { orderBy: "name", nocase: true }) {
81
+ if (selectopts.cached) {
82
+ const { getState } = require("../db/state");
83
+ return getState().views.map((t) => new View(t));
84
+ }
70
85
  const views = await db.select("_sc_views", where, selectopts);
71
86
 
72
87
  return views.map((v) => new View(v));
73
88
  }
74
89
 
75
90
  /**
76
- *
77
- * @returns {Promise<*|*[]>}
91
+ * @returns {Promise<object[]>}
78
92
  */
79
93
  async get_state_fields() {
80
94
  if (this.viewtemplateObj && this.viewtemplateObj.get_state_fields) {
@@ -88,7 +102,7 @@ class View {
88
102
 
89
103
  /**
90
104
  * Get menu label
91
- * @returns {*|undefined}
105
+ * @type {string|undefined}
92
106
  */
93
107
  get menu_label() {
94
108
  const { getState } = require("../db/state");
@@ -98,10 +112,9 @@ class View {
98
112
  }
99
113
 
100
114
  /**
101
- *
102
115
  * @param table
103
116
  * @param pred
104
- * @returns {Promise<*[]>}
117
+ * @returns {Promise<object[]>}
105
118
  */
106
119
  static async find_table_views_where(table, pred) {
107
120
  var link_view_opts = [];
@@ -133,6 +146,9 @@ class View {
133
146
  return link_view_opts;
134
147
  }
135
148
 
149
+ /**
150
+ * @type {object}
151
+ */
136
152
  get select_option() {
137
153
  return {
138
154
  name: this.name,
@@ -146,6 +162,10 @@ class View {
146
162
  };
147
163
  }
148
164
 
165
+ /**
166
+ * @param {function} pred
167
+ * @returns {Promise<object>}
168
+ */
149
169
  static async find_all_views_where(pred) {
150
170
  var link_view_opts = [];
151
171
  const link_views = await View.find({}, { orderBy: "name", nocase: true });
@@ -165,6 +185,10 @@ class View {
165
185
  return link_view_opts;
166
186
  }
167
187
 
188
+ /**
189
+ * @param {Table|object} table
190
+ * @returns {Promise<View[]>}
191
+ */
168
192
  static async find_possible_links_to_table(table) {
169
193
  return View.find_table_views_where(table, ({ state_fields }) =>
170
194
  state_fields.some((sf) => sf.name === "id" || sf.primary_key)
@@ -254,15 +278,27 @@ class View {
254
278
  await require("../db/state").getState().refresh_views();
255
279
  }
256
280
 
281
+ /**
282
+ * @param {*} arg
283
+ * @returns {Promise<object>}
284
+ */
257
285
  async authorise_post(arg) {
258
286
  if (!this.viewtemplateObj.authorise_post) return false;
259
287
  return await this.viewtemplateObj.authorise_post(arg);
260
288
  }
289
+
290
+ /**
291
+ * @param {*} arg
292
+ * @returns {Promise<object>}
293
+ */
261
294
  async authorise_get(arg) {
262
295
  if (!this.viewtemplateObj.authorise_get) return false;
263
296
  return await this.viewtemplateObj.authorise_get(arg);
264
297
  }
265
298
 
299
+ /**
300
+ * @returns {string}
301
+ */
266
302
  getStringsForI18n() {
267
303
  if (!this.viewtemplateObj || !this.viewtemplateObj.getStringsForI18n)
268
304
  return [];
@@ -290,12 +326,23 @@ class View {
290
326
  throw error;
291
327
  }
292
328
  }
329
+
330
+ /**
331
+ * @throws {InvalidConfiguration}
332
+ */
293
333
  check_viewtemplate() {
294
334
  if (!this.viewtemplateObj)
295
335
  throw new InvalidConfiguration(
296
336
  `Cannot find viewtemplate ${this.viewtemplate} in view ${this.name}`
297
337
  );
298
338
  }
339
+
340
+ /**
341
+ * @param {*} query
342
+ * @param {*} req
343
+ * @param {*} res
344
+ * @returns {Promise<object>}
345
+ */
299
346
  async run_possibly_on_page(query, req, res) {
300
347
  const view = this;
301
348
  this.check_viewtemplate();
@@ -317,6 +364,12 @@ class View {
317
364
  return contents;
318
365
  }
319
366
 
367
+ /**
368
+ * @param {*} query
369
+ * @param {*} extraArgs
370
+ * @throws {InvalidConfiguration}
371
+ * @returns {Promise<object>}
372
+ */
320
373
  async runMany(query, extraArgs) {
321
374
  this.check_viewtemplate();
322
375
  try {
@@ -354,6 +407,13 @@ class View {
354
407
  `runMany on view ${this.name}: viewtemplate ${this.viewtemplate} does not have renderRows or runMany methods`
355
408
  );
356
409
  }
410
+
411
+ /**
412
+ * @param {*} query
413
+ * @param {*} body
414
+ * @param {*} extraArgs
415
+ * @returns {Promise<object>}
416
+ */
357
417
  async runPost(query, body, extraArgs) {
358
418
  this.check_viewtemplate();
359
419
  return await this.viewtemplateObj.runPost(
@@ -366,6 +426,13 @@ class View {
366
426
  );
367
427
  }
368
428
 
429
+ /**
430
+ * @param {*} route
431
+ * @param {*} body
432
+ * @param {*} res
433
+ * @param {*} extraArgs
434
+ * @returns {Promise<void>}
435
+ */
369
436
  async runRoute(route, body, res, extraArgs) {
370
437
  this.check_viewtemplate();
371
438
  const result = await this.viewtemplateObj.routes[route](
@@ -380,6 +447,10 @@ class View {
380
447
  else res.json({ success: "ok" });
381
448
  }
382
449
 
450
+ /**
451
+ * @param {object} req_query
452
+ * @returns {object}
453
+ */
383
454
  combine_state_and_default_state(req_query) {
384
455
  var state = { ...req_query };
385
456
  this.check_viewtemplate();
@@ -394,6 +465,12 @@ class View {
394
465
  });
395
466
  return state;
396
467
  }
468
+
469
+ /**
470
+ * @param {object} query
471
+ * @param {object} req
472
+ * @returns {Promise<Form|null>}
473
+ */
397
474
  async get_state_form(query, req) {
398
475
  this.check_viewtemplate();
399
476
  const vt_display_state_form = this.viewtemplateObj.display_state_form;
@@ -427,6 +504,10 @@ class View {
427
504
  } else return null;
428
505
  }
429
506
 
507
+ /**
508
+ * @param {object} req
509
+ * @returns {Promise<object>}
510
+ */
430
511
  async get_config_flow(req) {
431
512
  this.check_viewtemplate();
432
513
  const configFlow = this.viewtemplateObj.configuration_workflow(req);
@@ -1,10 +1,24 @@
1
+ /**
2
+ * view description
3
+ * @category saltcorn-data
4
+ * @module models/workflow
5
+ * @subcategory models
6
+ */
1
7
  const db = require("../db");
2
8
  const { getState } = require("../db/state");
3
9
  const Field = require("./field");
4
10
  const { contract, is } = require("contractis");
5
11
  const { applyAsync, apply } = require("../utils");
6
12
 
13
+ /**
14
+ * Workflow class
15
+ * @category saltcorn-data
16
+ */
7
17
  class Workflow {
18
+ /**
19
+ * Workflow constructor
20
+ * @param {*} o
21
+ */
8
22
  constructor(o) {
9
23
  this.steps = o.steps || [];
10
24
  this.onDone = o.onDone || ((c) => c);
@@ -12,6 +26,12 @@ class Workflow {
12
26
  this.__ = (s) => s;
13
27
  contract.class(this);
14
28
  }
29
+
30
+ /**
31
+ * @param {object} body
32
+ * @param {object} req
33
+ * @returns {Promise<object>}
34
+ */
15
35
  async run(body, req) {
16
36
  if (req) this.__ = (s) => req.__(s);
17
37
  if (!body || !body.stepName) {
@@ -77,6 +97,12 @@ class Workflow {
77
97
  return this.runStep({ ...context, ...toCtx }, stepIx + 1);
78
98
  }
79
99
  }
100
+
101
+ /**
102
+ * @param {object} context
103
+ * @param {number} stepIx
104
+ * @returns {Promise<object>}
105
+ */
80
106
  async runStep(context, stepIx) {
81
107
  if (stepIx >= this.steps.length) {
82
108
  return await this.onDone(context);
@@ -149,6 +175,11 @@ class Workflow {
149
175
  }
150
176
  }
151
177
 
178
+ /**
179
+ * @param {object} step
180
+ * @param {number} stepIx
181
+ * @returns {string}
182
+ */
152
183
  title(step, stepIx) {
153
184
  return `${step.name} (${this.__("step")} ${stepIx + 1} / ${
154
185
  this.steps.length > stepIx + 1 ? this.__("max") + " " : ""
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/data",
3
- "version": "0.6.1-beta.0",
3
+ "version": "0.6.1",
4
4
  "description": "Data models for Saltcorn, open-source no-code platform",
5
5
  "homepage": "https://saltcorn.com",
6
6
  "scripts": {
@@ -9,8 +9,13 @@
9
9
  "author": "Tom Nielsen",
10
10
  "license": "MIT",
11
11
  "main": "index.js",
12
+ "optionalDependencies": {
13
+ "@saltcorn/postgres": "0.6.1",
14
+ "@saltcorn/sqlite": "0.6.1"
15
+ },
12
16
  "dependencies": {
13
- "@saltcorn/markup": "0.6.1-beta.0",
17
+ "@saltcorn/markup": "0.6.1",
18
+ "@saltcorn/db-common": "0.6.1",
14
19
  "acorn": "^8.0.3",
15
20
  "adm-zip": "0.5.5",
16
21
  "astring": "^1.4.3",
@@ -32,10 +37,7 @@
32
37
  "moment-timezone": "^0.5.33",
33
38
  "node-fetch": "2.6.2",
34
39
  "nodemailer": "^6.4.17",
35
- "pg": "^8.2.1",
36
- "pg-copy-streams": "^5.1.1",
37
40
  "pluralize": "^8.0.0",
38
- "sqlite3": "^5.0.2",
39
41
  "tmp-promise": "^3.0.2",
40
42
  "uuid": "^8.2.0"
41
43
  },
package/plugin-helper.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Plugin-helper
3
- *
3
+ * @category saltcorn-data
4
+ * @module plugin-helper
4
5
  */
5
6
  const View = require("./models/view");
6
7
  const Field = require("./models/field");
@@ -22,14 +23,17 @@ const { applyAsync, InvalidConfiguration } = require("./utils");
22
23
  const { jsexprToSQL } = require("./models/expression");
23
24
  /**
24
25
  *
25
- * @param url
26
- * @param label
27
- * @param popup
28
- * @param link_style
29
- * @param link_size
30
- * @param link_icon
31
- * @param textStyle
32
- * @returns {string}
26
+ * @param {string} url
27
+ * @param {string} label
28
+ * @param {boolean} [popup]
29
+ * @param {string} [link_style = ""]
30
+ * @param {string} [link_size = ""]
31
+ * @param {string} [link_icon = ""]
32
+ * @param {string} [textStyle = ""]
33
+ * @param {string} [link_bgcol]
34
+ * @param {string} [link_bordercol]
35
+ * @param {string} [link_textcol]
36
+ * @returns {button|a}
33
37
  */
34
38
  const link_view = (
35
39
  url,
@@ -76,6 +80,11 @@ const link_view = (
76
80
  );
77
81
  };
78
82
 
83
+ /**
84
+ * @function
85
+ * @param {object} [state]
86
+ * @returns {string}
87
+ */
79
88
  const stateToQueryString = contract(
80
89
  is.fun(is.maybe(is.obj()), is.str),
81
90
  (state) => {
@@ -94,9 +103,12 @@ const stateToQueryString = contract(
94
103
  );
95
104
  }
96
105
  );
106
+
97
107
  /**
98
- *
99
- * @type {*|(function(...[*]=): *)}
108
+ * @function
109
+ * @param {Field[]} fields
110
+ * @param {boolean}
111
+ * @returns {object}
100
112
  */
101
113
  const calcfldViewOptions = contract(
102
114
  is.fun(
@@ -148,9 +160,12 @@ const calcfldViewOptions = contract(
148
160
  return { field_view_options: fvs, handlesTextStyle };
149
161
  }
150
162
  );
163
+
151
164
  /**
152
- *
153
- * @type {*|(function(...[*]=): *)}
165
+ * @function
166
+ * @param {Field[]} fields
167
+ * @param {boolean}
168
+ * @returns {Promise<object>}
154
169
  */
155
170
  const calcfldViewConfig = contract(
156
171
  is.fun([is.array(is.class("Field")), is.bool], is.promise(is.obj())),
@@ -173,9 +188,13 @@ const calcfldViewConfig = contract(
173
188
  return fieldViewConfigForms;
174
189
  }
175
190
  );
191
+
176
192
  /**
177
- *
178
- * @type {*|(function(...[*]=): *)}
193
+ * @function
194
+ * @param {Table|object} table
195
+ * @param {string} viewname
196
+ * @param {boolean}
197
+ * @returns {Promise<object[]>}
179
198
  */
180
199
  const get_link_view_opts = contract(
181
200
  is.fun(
@@ -235,19 +254,24 @@ const get_link_view_opts = contract(
235
254
  return link_view_opts;
236
255
  }
237
256
  );
257
+
238
258
  /**
239
259
  * Get Action configuration fields
240
- * @param action
241
- * @param table
242
- * @returns {Promise<*|[{name: string, label: string, type: string}, {name: string, label: string, type: string, sublabel: string}]|[{name: string, label: string, type: string, sublabel: string}]|[{name: string, type: string}]|[{name: string, label: string, type: string}]|*|*[]>}
260
+ * @param {object} action
261
+ * @param {object} table
262
+ * @returns {Promise<object[]>}
243
263
  */
244
264
  const getActionConfigFields = async (action, table) =>
245
265
  typeof action.configFields === "function"
246
266
  ? await action.configFields({ table })
247
267
  : action.configFields || [];
268
+
248
269
  /**
249
- *
250
- * @type {*|(function(...[*]=): *)}
270
+ * @function
271
+ * @param {Table|object} table
272
+ * @param {string} viewname
273
+ * @param {object} req
274
+ * @returns {Promise<object[]>}
251
275
  */
252
276
  const field_picker_fields = contract(
253
277
  is.fun(
@@ -652,9 +676,13 @@ const field_picker_fields = contract(
652
676
  ];
653
677
  }
654
678
  );
679
+
655
680
  /**
656
681
  * get_child_views Contract
657
- * @type {*|(function(...[*]=): *)}
682
+ * @function
683
+ * @param {Table|object} table
684
+ * @param {string} viewname
685
+ * @returns {Promise<object[]>}
658
686
  */
659
687
  const get_child_views = contract(
660
688
  is.fun(
@@ -684,9 +712,13 @@ const get_child_views = contract(
684
712
  return child_views;
685
713
  }
686
714
  );
715
+
687
716
  /**
688
717
  * get_parent_views Contract
689
- * @type {*|(function(...[*]=): *)}
718
+ * @function
719
+ * @param {Table|object} table
720
+ * @param {string} viewname
721
+ * @returns {Promise<object[]>}
690
722
  */
691
723
  const get_parent_views = contract(
692
724
  is.fun(
@@ -722,9 +754,13 @@ const get_parent_views = contract(
722
754
  return parent_views;
723
755
  }
724
756
  );
757
+
725
758
  /**
726
759
  * get_onetoone_views Contract
727
- * @type {*|(function(...[*]=): *)}
760
+ * @function
761
+ * @param {Table|is_tablely} table
762
+ * @param {string} viewname
763
+ * @returns {Promise<object[]>}
728
764
  */
729
765
  const get_onetoone_views = contract(
730
766
  is.fun(
@@ -761,7 +797,11 @@ const get_onetoone_views = contract(
761
797
 
762
798
  /**
763
799
  * picked_fields_to_query Contract
764
- * @type {*|(function(...[*]=): *)}
800
+ * @function
801
+ * @param {object[]} columns
802
+ * @param {Field[]} fields
803
+ * @throws {InvalidConfiguration}
804
+ * @returns {object}
765
805
  */
766
806
  const picked_fields_to_query = contract(
767
807
  is.fun([is.array(is_column), is.array(is.class("Field"))], is_table_query),
@@ -831,9 +871,13 @@ const picked_fields_to_query = contract(
831
871
  return { joinFields, aggregations };
832
872
  }
833
873
  );
874
+
834
875
  /**
835
- *
836
- * @type {*|(function(...[*]=): *)}
876
+ * @function
877
+ * @param {object}
878
+ * @param {object}
879
+ * @param {string} - missing in contract
880
+ * @returns {object}
837
881
  */
838
882
  const stateFieldsToQuery = contract(
839
883
  is.fun(is.obj(), is.obj()),
@@ -863,19 +907,26 @@ const stateFieldsToQuery = contract(
863
907
  return q;
864
908
  }
865
909
  );
910
+
866
911
  /**
867
912
  *
868
- * @param container
869
- * @param key
870
- * @param x
913
+ * @param {object} container
914
+ * @param {string} key
915
+ * @param {object} x
916
+ * @returns {void}
871
917
  */
872
918
  const addOrCreateList = (container, key, x) => {
873
919
  if (container[key]) container[key].push(x);
874
920
  else container[key] = [x];
875
921
  };
922
+
876
923
  /**
877
- *
878
- * @type {*|(function(...[*]=): *)}
924
+ * @function
925
+ * @param {object} opts
926
+ * @param {Field[]} opts.fields
927
+ * @param {object} opts.state missing in contract
928
+ * @param {boolean} [opts.approximate = true]
929
+ * @returns {object}
879
930
  */
880
931
  const stateFieldsToWhere = contract(
881
932
  is.fun(
@@ -936,9 +987,12 @@ const stateFieldsToWhere = contract(
936
987
  return qstate;
937
988
  }
938
989
  );
990
+
939
991
  /**
940
992
  * initial_config_all_fields Contract
941
- * @type {*|(function(...[*]=): *)}
993
+ * @function
994
+ * @param {boolean}
995
+ * @returns {function}
942
996
  */
943
997
  const initial_config_all_fields = contract(
944
998
  is.fun(
@@ -1049,20 +1103,22 @@ const initial_config_all_fields = contract(
1049
1103
  return cfg;
1050
1104
  }
1051
1105
  );
1106
+
1052
1107
  /**
1053
1108
  *
1054
- * @param x
1109
+ * @param {string} x
1055
1110
  * @returns {number|undefined}
1056
1111
  */
1057
1112
  const strictParseInt = (x) => {
1058
1113
  const y = +x;
1059
1114
  return !isNaN(y) && y ? y : undefined;
1060
1115
  };
1116
+
1061
1117
  /**
1062
1118
  *
1063
- * @param state
1064
- * @param fields
1065
- * @returns {*}
1119
+ * @param {object} state
1120
+ * @param {object[]} fields
1121
+ * @returns {object}
1066
1122
  */
1067
1123
  const readState = (state, fields, req) => {
1068
1124
  fields.forEach((f) => {
@@ -1081,10 +1137,11 @@ const readState = (state, fields, req) => {
1081
1137
  });
1082
1138
  return state;
1083
1139
  };
1140
+
1084
1141
  /**
1085
1142
  *
1086
- * @param state
1087
- * @param fields
1143
+ * @param {object} state
1144
+ * @param {object[]} fields
1088
1145
  * @returns {boolean|*}
1089
1146
  */
1090
1147
  const readStateStrict = (state, fields) => {
@@ -1116,9 +1173,9 @@ const readStateStrict = (state, fields) => {
1116
1173
  };
1117
1174
  /**
1118
1175
  *
1119
- * @param get_json_list
1120
- * @param fields0
1121
- * @returns {any[]|{child_relations: *[], child_field_list: *[]}|{readonly min_role_read: *, get_child_relations(): {child_relations: [], child_field_list: []}, external: boolean, getFields(): *, owner_fieldname(): null, getJoinedRows(*=): Promise<*|*>, countRows(*): Promise<*>, distinctValues(*): Promise<*>, getRows: ((function(*=, *=): Promise<*|*>)|*), fields, get_parent_relations(): {parent_relations: [], parent_field_list: []}}|{parent_relations: *[], parent_field_list: *[]}|null|*|number|Promise<*|*>}
1176
+ * @param {function} get_json_list
1177
+ * @param {object[]} fields0
1178
+ * @returns {object}
1122
1179
  */
1123
1180
  const json_list_to_external_table = (get_json_list, fields0) => {
1124
1181
  const fields = fields0.map((f) =>
@@ -1186,11 +1243,12 @@ const json_list_to_external_table = (get_json_list, fields0) => {
1186
1243
  };
1187
1244
  return tbl;
1188
1245
  };
1246
+
1189
1247
  /**
1190
1248
  *
1191
- * @param col
1192
- * @param req
1193
- * @param rest
1249
+ * @param {object} col
1250
+ * @param {object} req
1251
+ * @param {...*} rest
1194
1252
  * @returns {Promise<*>}
1195
1253
  */
1196
1254
  const run_action_column = async ({ col, req, ...rest }) => {
package/plugin-testing.js CHANGED
@@ -1,3 +1,7 @@
1
+ /**
2
+ * @category saltcorn-data
3
+ * @module plugin-testing
4
+ */
1
5
  const { contract, is, auto_test } = require("contractis");
2
6
  const { is_plugin_wrap, is_plugin } = require("./contracts");
3
7
  const { getState } = require("./db/state");