@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/db/connect.js CHANGED
@@ -1,7 +1,10 @@
1
1
  /**
2
2
  * Controls Saltcorn configuration
3
- * @type {path.PlatformPath | path}
3
+ * @category saltcorn-data
4
+ * @module db/connect
5
+ * @subcategory db
4
6
  */
7
+
5
8
  const path = require("path");
6
9
  const fs = require("fs");
7
10
  const envPaths = require("env-paths");
@@ -13,13 +16,18 @@ const pathsWithApp = envPaths("saltcorn", { suffix: "" });
13
16
  * @type {string}
14
17
  */
15
18
  const defaultDataPath = pathsWithApp.data;
19
+
20
+ /**
21
+ * @param {string|object} x
22
+ * @returns {object}
23
+ */
16
24
  const stringToJSON = (x) => (typeof x === "string" ? JSON.parse(x) : x);
17
25
  /**
18
26
  * Get Git revision of Saltcorn source.
19
27
  * Required to work:
20
28
  * - Git client installed,
21
29
  * - Local git with repo Saltcorn sources.
22
- * @returns {null} - Return current Git commit
30
+ * @returns {string} - Return current Git commit
23
31
  */
24
32
  const getGitRevision = () => {
25
33
  let revision = null;
@@ -41,8 +49,8 @@ const getGitRevision = () => {
41
49
  * - File store path
42
50
  * - Saltcorn confuration inheritance and fixed configuration
43
51
  * For all parameters and priority see the code of function.
44
- * @param connSpec
45
- * @returns {{sc_version: string, connectionString: *, git_commit: *, version_tag: (*|string)}|{sqlite_path}|boolean}
52
+ * @param {object} [connSpec = {}]
53
+ * @returns {object|boolean}
46
54
  */
47
55
  const getConnectObject = (connSpec = {}) => {
48
56
  const git_commit = getGitRevision();
@@ -123,7 +131,7 @@ const getConfigFile = () => {
123
131
  };
124
132
  /**
125
133
  * Check that Saltcorn configured to use SQLite as database
126
- * @param connObj - connectin object
134
+ * @param {object} connObj - connectin object
127
135
  * @returns {boolean} - Returns true if Saltcorn configured to use SQLite as database
128
136
  */
129
137
  const is_sqlite = (connObj) => {
package/db/db.test.js CHANGED
@@ -1,162 +1,8 @@
1
- const { sqlsanitize, mkWhere, sqlsanitizeAllowDots } = require("./internal");
2
1
  const db = require("./index.js");
3
2
  const Table = require("../models/table");
4
3
 
5
4
  afterAll(db.close);
6
5
 
7
- describe("sqlsanitize", () => {
8
- it("should not alter valid name", () => {
9
- expect(sqlsanitize("ffoo_oo")).toBe("ffoo_oo");
10
- });
11
- it("should remove spaces", () => {
12
- expect(sqlsanitize(" ")).toBe("");
13
- });
14
- it("should remove chars from invalid name", () => {
15
- expect(sqlsanitize("ffoo--oo--uu")).toBe("ffoooouu");
16
- });
17
- it("should not allow dots", () => {
18
- expect(sqlsanitize("ffoo.oo")).toBe("ffoooo");
19
- });
20
- it("should allow dots when specified", () => {
21
- expect(sqlsanitizeAllowDots("ffoo.oo")).toBe("ffoo.oo");
22
- });
23
- it("should allow quotes when dots specified", () => {
24
- expect(sqlsanitizeAllowDots('ffoo."oo"')).toBe('ffoo."oo"');
25
- });
26
- it("should allow numbers", () => {
27
- expect(sqlsanitize("ff1oo_oo")).toBe("ff1oo_oo");
28
- });
29
- it("should not allow numbers in initial position", () => {
30
- expect(sqlsanitize("1ffoo_o1o")).toBe("_1ffoo_o1o");
31
- });
32
- });
33
-
34
- describe("mkWhere", () => {
35
- it("should empty on no arg", () => {
36
- expect(mkWhere()).toStrictEqual({ values: [], where: "" });
37
- });
38
- it("should empty on null obj arg", () => {
39
- expect(mkWhere({})).toStrictEqual({ values: [], where: "" });
40
- });
41
- it("should query json", () => {
42
- expect(mkWhere({ foo: { json: ["bar", 5] } })).toStrictEqual({
43
- values: [5],
44
- where: `where "foo"->>'bar'=$1`,
45
- });
46
- });
47
-
48
- it("should set id", () => {
49
- expect(mkWhere({ id: 5 })).toStrictEqual({
50
- values: [5],
51
- where: 'where "id"=$1',
52
- });
53
- expect(mkWhere({ id: 5, hello: "world" })).toStrictEqual({
54
- values: [5, "world"],
55
- where: 'where "id"=$1 and "hello"=$2',
56
- });
57
- });
58
- it("should query null", () => {
59
- expect(mkWhere({ id: null })).toStrictEqual({
60
- values: [],
61
- where: 'where "id" is null',
62
- });
63
- expect(mkWhere({ id: null, foo: 1 })).toStrictEqual({
64
- values: [1],
65
- where: 'where "id" is null and "foo"=$1',
66
- });
67
- expect(mkWhere({ foo: 1, id: null })).toStrictEqual({
68
- values: [1],
69
- where: 'where "foo"=$1 and "id" is null',
70
- });
71
- });
72
- it("should query lt/gt", () => {
73
- expect(mkWhere({ id: { lt: 5 } })).toStrictEqual({
74
- values: [5],
75
- where: 'where "id"<$1',
76
- });
77
- expect(mkWhere({ id: { gt: 8 } })).toStrictEqual({
78
- values: [8],
79
- where: 'where "id">$1',
80
- });
81
- expect(mkWhere({ id: { lt: 5, equal: true } })).toStrictEqual({
82
- values: [5],
83
- where: 'where "id"<=$1',
84
- });
85
- expect(mkWhere({ id: { gt: 8, equal: true } })).toStrictEqual({
86
- values: [8],
87
- where: 'where "id">=$1',
88
- });
89
- expect(mkWhere({ id: [{ gt: 0 }, { lt: 10 }] })).toStrictEqual({
90
- values: [0, 10],
91
- where: 'where "id">$1 and "id"<$2',
92
- });
93
- expect(mkWhere({ id: { or: [{ gt: 10 }, { lt: 5 }] } })).toStrictEqual({
94
- values: [10, 5],
95
- where: 'where ("id">$1 or "id"<$2)',
96
- });
97
- });
98
- it("should query subselect", () => {
99
- expect(
100
- mkWhere({
101
- id: [{ inSelect: { table: "foo", field: "bar", where: { baz: 7 } } }],
102
- })
103
- ).toStrictEqual({
104
- values: [7],
105
- where: 'where "id" in (select bar from foo where "baz"=$1)',
106
- });
107
- expect(
108
- mkWhere({
109
- age: 45,
110
- id: [{ inSelect: { table: "foo", field: "bar", where: { baz: 7 } } }],
111
- name: "Alice",
112
- })
113
- ).toStrictEqual({
114
- values: [45, 7, "Alice"],
115
- where: `where "age"=$1 and "id" in (select bar from foo where "baz"=$2) and "name"=$3`,
116
- });
117
- });
118
- it("should query or", () => {
119
- expect(mkWhere({ or: [{ id: 5 }, { x: 7 }] })).toStrictEqual({
120
- values: [5, 7],
121
- where: 'where ("id"=$1 or "x"=$2)',
122
- });
123
- expect(mkWhere({ or: [{ id: 5 }, { x: { gt: 7 } }] })).toStrictEqual({
124
- values: [5, 7],
125
- where: 'where ("id"=$1 or "x">$2)',
126
- });
127
- expect(mkWhere({ or: [{ id: 5 }, { x: 7, y: 8 }] })).toStrictEqual({
128
- values: [5, 7, 8],
129
- where: 'where ("id"=$1 or "x"=$2 and "y"=$3)',
130
- });
131
- expect(mkWhere({ not: { id: 5 } })).toStrictEqual({
132
- values: [5],
133
- where: 'where not ("id"=$1)',
134
- });
135
- expect(mkWhere({ not: { id: 5, y: 1 } })).toStrictEqual({
136
- values: [5, 1],
137
- where: 'where not ("id"=$1 and "y"=$2)',
138
- });
139
- expect(mkWhere({ not: { y: { in: [1, 2, 3] } } })).toStrictEqual({
140
- values: [[1, 2, 3]],
141
- where: 'where not ("y" = ANY ($1))',
142
- });
143
- expect(mkWhere({ y: { in: [1, 2, 3] } })).toStrictEqual({
144
- values: [[1, 2, 3]],
145
- where: 'where "y" = ANY ($1)',
146
- });
147
- /*
148
- TODO
149
- expect(mkWhere([{ id: 5 }, { x: 7 }])).toStrictEqual({
150
- values: [5, 7],
151
- where: 'where "id"=$1 and "x"=$2',
152
- });
153
- expect(mkWhere([{ or: [{ id: 5 }, { x: 7 }] }, { z: 9 }])).toStrictEqual({
154
- values: [5, 7, 9],
155
- where: 'where ("id"=$1 or "x"=$2) and "z"=$3',
156
- });*/
157
- });
158
- });
159
-
160
6
  describe("where", () => {
161
7
  it("should support in", async () => {
162
8
  await Table.create("myothertable");
package/db/fixtures.js CHANGED
@@ -1,3 +1,9 @@
1
+ /**
2
+ * init fixtures
3
+ * @category saltcorn-data
4
+ * @module db/fixtures
5
+ * @subcategory db
6
+ */
1
7
  const db = require(".");
2
8
  const { getState } = require("./state");
3
9
  const Table = require("../models/table");
@@ -8,7 +14,13 @@ const User = require("../models/user");
8
14
  const Page = require("../models/page");
9
15
  const fs = require("fs").promises;
10
16
 
11
- module.exports = async () => {
17
+ module.exports =
18
+ /**
19
+ * @function
20
+ * @name "module.exports function"
21
+ * @returns {Promise<void>}
22
+ */
23
+ async () => {
12
24
  getState().registerPlugin("base", require("../base-plugin"));
13
25
  const table = await Table.create("books", {
14
26
  min_role_read: 10,
package/db/index.js CHANGED
@@ -1,21 +1,60 @@
1
+ /**
2
+ * init fixtures
3
+ * @category saltcorn-data
4
+ * @module db/index
5
+ * @subcategory db
6
+ */
7
+
8
+ /**
9
+ * All files in the db module.
10
+ * @namespace db_overview
11
+ * @property {module:db/connect} connect
12
+ * @property {module:db/fixtures} fixtures
13
+ * @property {module:db/reset_schema} reset_schema
14
+ * @property {module:db/state} state
15
+ * @property {module:db/connect} connect
16
+ *
17
+ * @category saltcorn-data
18
+ * @subcategory db
19
+ */
1
20
  const { getConnectObject, is_sqlite } = require("./connect");
2
- const { sqlsanitize, mkWhere } = require("./internal");
21
+ const { sqlsanitize, mkWhere } = require("@saltcorn/db-common/internal");
3
22
  var connectObj = getConnectObject();
4
23
 
5
- const dbmodule = is_sqlite(connectObj) ? require("./sqlite") : require("./pg");
24
+ /** @type {db/sqlite|db/pg|null} */
25
+ let dbmodule = null;
26
+ try {
27
+ dbmodule = is_sqlite(connectObj) ?
28
+ require("@saltcorn/sqlite/sqlite")(getConnectObject) :
29
+ require("@saltcorn/postgres/postgres")(getConnectObject);
30
+ } catch(e) {
31
+ console.log("No database package found.")
32
+ throw e;
33
+ }
6
34
 
7
- const tenant = require("./tenants");
35
+ /** @type {db/tenant} */
36
+ const tenant = require("@saltcorn/db-common/tenants")(getConnectObject());
8
37
 
38
+ /** @type {boolean} */
9
39
  const isSQLite = is_sqlite(connectObj);
10
40
 
41
+ /**
42
+ * @returns {string}
43
+ */
11
44
  const getTenantSchemaPrefix = () =>
12
45
  isSQLite ? "" : `"${tenant.getTenantSchema()}".`;
46
+
13
47
  module.exports = {
14
48
  ...tenant,
15
49
  sqlsanitize,
16
50
  connectObj,
17
51
  isSQLite,
18
52
  ...dbmodule,
53
+ /**
54
+ * @param {object} q
55
+ * @returns {function}
56
+ */
19
57
  mkWhere: (q) => mkWhere(q, isSQLite),
20
58
  getTenantSchemaPrefix,
21
59
  };
60
+
@@ -1,4 +1,15 @@
1
+ /**
2
+ * @category saltcorn-data
3
+ * @module db/reset_schema
4
+ * @subcategory db
5
+ */
6
+
1
7
  //https://stackoverflow.com/a/21247009
8
+ /**
9
+ * @param {boolean} dontDrop
10
+ * @param {string} schema0
11
+ * @returns {Promise<void>}
12
+ */
2
13
  const reset = async (dontDrop = false, schema0) => {
3
14
  const db = require(".");
4
15
  const { migrate } = require("../migrate");
package/db/state.js CHANGED
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * State of Saltcorn
3
3
  * Keeps cache for main objects
4
+ * @category saltcorn-data
5
+ * @module db/state
6
+ * @subcategory db
4
7
  */
5
-
6
8
  const { contract, is } = require("contractis");
7
9
  const {
8
10
  is_plugin_wrap,
@@ -19,7 +21,11 @@ const { migrate } = require("../migrate");
19
21
  const File = require("../models/file");
20
22
  const Trigger = require("../models/trigger");
21
23
  const View = require("../models/view");
22
- const { getAllTenants, createTenant } = require("../models/tenant");
24
+ const {
25
+ getAllTenants,
26
+ createTenant,
27
+ copy_tenant_template,
28
+ } = require("../models/tenant");
23
29
  const {
24
30
  getAllConfigOrDefaults,
25
31
  setConfig,
@@ -32,14 +38,23 @@ const { I18n } = require("i18n");
32
38
  const path = require("path");
33
39
  const fs = require("fs");
34
40
 
41
+ /**
42
+ * @param {object} v
43
+ * @returns {void}
44
+ */
35
45
  const process_send = (v) => {
36
46
  if (process.send) process.send(v);
37
47
  };
38
48
 
39
49
  /**
40
- * State class
50
+ * State Class
51
+ * @category saltcorn-data
41
52
  */
42
53
  class State {
54
+ /**
55
+ * State constructor
56
+ * @param {string} tenant description
57
+ */
43
58
  constructor(tenant) {
44
59
  this.tenant = tenant;
45
60
  this.views = [];
@@ -78,8 +93,8 @@ class State {
78
93
  /**
79
94
  * Get Layout by user
80
95
  * Based on role of user
81
- * @param user
82
- * @returns {unknown}
96
+ * @param {object} user
97
+ * @returns {object}
83
98
  */
84
99
  getLayout(user) {
85
100
  const role_id = user ? +user.role_id : 10;
@@ -94,6 +109,7 @@ class State {
94
109
 
95
110
  /**
96
111
  * Refresh State cache for all Saltcorn main objects
112
+ * @param {boolean} noSignal
97
113
  * @returns {Promise<void>}
98
114
  */
99
115
  async refresh(noSignal) {
@@ -104,8 +120,10 @@ class State {
104
120
  await this.refresh_pages(noSignal);
105
121
  await this.refresh_config(noSignal);
106
122
  }
123
+
107
124
  /**
108
125
  * Refresh config
126
+ * @param {boolean} noSignal
109
127
  * @returns {Promise<void>}
110
128
  */
111
129
  async refresh_config(noSignal) {
@@ -117,6 +135,10 @@ class State {
117
135
  if (!noSignal)
118
136
  process_send({ refresh: "config", tenant: db.getTenantSchema() });
119
137
  }
138
+
139
+ /**
140
+ * @returns {Promise<void>}
141
+ */
120
142
  async refresh_i18n() {
121
143
  const localeDir = path.join(__dirname, "..", "app-locales", this.tenant);
122
144
  try {
@@ -144,6 +166,7 @@ class State {
144
166
 
145
167
  /**
146
168
  * Refresh views
169
+ * @param {boolean} noSignal
147
170
  * @returns {Promise<void>}
148
171
  */
149
172
  async refresh_views(noSignal) {
@@ -166,6 +189,7 @@ class State {
166
189
 
167
190
  /**
168
191
  * Refresh triggers
192
+ * @param {boolean} noSignal
169
193
  * @returns {Promise<void>}
170
194
  */
171
195
  async refresh_triggers(noSignal) {
@@ -176,6 +200,7 @@ class State {
176
200
 
177
201
  /**
178
202
  * Refresh pages
203
+ * @param {boolean} noSignal
179
204
  * @returns {Promise<void>}
180
205
  */
181
206
  async refresh_pages(noSignal) {
@@ -187,6 +212,7 @@ class State {
187
212
 
188
213
  /**
189
214
  * Refresh files
215
+ * @param {boolean} noSignal
190
216
  * @returns {Promise<void>}
191
217
  */
192
218
  // todo what will be if there are a lot of files? Yes, there are cache only ids of files.
@@ -202,6 +228,7 @@ class State {
202
228
 
203
229
  /**
204
230
  * Refresh tables & fields
231
+ * @param {boolean} noSignal
205
232
  * @returns {Promise<void>}
206
233
  */
207
234
  async refresh_tables(noSignal) {
@@ -244,9 +271,9 @@ class State {
244
271
 
245
272
  /**
246
273
  * Get config parameter by key
247
- * @param key - key of config paramter
248
- * @param def - default value
249
- * @returns {*}
274
+ * @param {string} key - key of config paramter
275
+ * @param {string} [def] - default value
276
+ * @returns {string}
250
277
  */
251
278
  getConfig(key, def) {
252
279
  const fixed = db.connectObj.fixed_configuration[key];
@@ -264,9 +291,9 @@ class State {
264
291
 
265
292
  /**
266
293
  * Get copy of config parameter
267
- * @param key - key of parameter
268
- * @param def - default value
269
- * @returns {any}
294
+ * @param {sring} key - key of parameter
295
+ * @param {string} [def] - default value
296
+ * @returns {string}
270
297
  */
271
298
  getConfigCopy(key, def) {
272
299
  return structuredClone(this.getConfig(key, def));
@@ -275,8 +302,8 @@ class State {
275
302
  /**
276
303
  *
277
304
  * Set value of config parameter
278
- * @param key - key of parameter
279
- * @param value - value of parameter
305
+ * @param {string} key - key of parameter
306
+ * @param {string} value - value of parameter
280
307
  * @returns {Promise<void>}
281
308
  */
282
309
  async setConfig(key, value) {
@@ -294,7 +321,7 @@ class State {
294
321
 
295
322
  /**
296
323
  * Delete config parameter by key
297
- * @param key - key of parameter
324
+ * @param {string} key - key of parameter
298
325
  * @returns {Promise<void>}
299
326
  */
300
327
  async deleteConfig(...keys) {
@@ -306,11 +333,13 @@ class State {
306
333
  }
307
334
 
308
335
  /**
309
- * Registre plugin
310
- * @param name
311
- * @param plugin
312
- * @param cfg
313
- * @param location
336
+ * Register plugin
337
+ * @param {string} name
338
+ * @param {object} plugin
339
+ * @param {*} cfg
340
+ * @param {*} location
341
+ * @param {string} modname
342
+ * @returns {void}
314
343
  */
315
344
  registerPlugin(name, plugin, cfg, location, modname) {
316
345
  this.plugins[name] = plugin;
@@ -381,7 +410,7 @@ class State {
381
410
 
382
411
  /**
383
412
  * Get type names
384
- * @returns {string[]}
413
+ * @type {string[]}
385
414
  */
386
415
  get type_names() {
387
416
  return Object.keys(this.types);
@@ -389,7 +418,7 @@ class State {
389
418
 
390
419
  /**
391
420
  * Add type
392
- * @param t
421
+ * @param {object} t
393
422
  */
394
423
  addType(t) {
395
424
  this.types[t.name] = {
@@ -403,7 +432,8 @@ class State {
403
432
 
404
433
  /**
405
434
  * Remove plugin
406
- * @param name
435
+ * @param {string} name
436
+ * @param {boolean} noSignal
407
437
  * @returns {Promise<void>}
408
438
  */
409
439
  async remove_plugin(name, noSignal) {
@@ -415,6 +445,7 @@ class State {
415
445
 
416
446
  /**
417
447
  * Reload plugins
448
+ * @param {boolean} noSignal
418
449
  * @returns {Promise<void>}
419
450
  */
420
451
  async refresh_plugins(noSignal) {
@@ -441,6 +472,9 @@ class State {
441
472
  process_send({ refresh: "plugins", tenant: db.getTenantSchema() });
442
473
  }
443
474
 
475
+ /**
476
+ * @returns {string[]}
477
+ */
444
478
  getStringsForI18n() {
445
479
  const strings = [];
446
480
  this.views.forEach((v) => strings.push(...v.getStringsForI18n()));
@@ -452,10 +486,18 @@ class State {
452
486
  );
453
487
  }
454
488
 
489
+ /**
490
+ *
491
+ * @param {function} f
492
+ */
455
493
  setRoomEmitter(f) {
456
494
  this.roomEmitter = f;
457
495
  }
458
496
 
497
+ /**
498
+ *
499
+ * @param {*} args
500
+ */
459
501
  emitRoom(...args) {
460
502
  if (this.roomEmitter) this.roomEmitter(...args);
461
503
  }
@@ -483,6 +525,11 @@ State.contract = {
483
525
  const singleton = new State("public");
484
526
 
485
527
  // return current State object
528
+
529
+ /**
530
+ * @function
531
+ * @returns {State}
532
+ */
486
533
  const getState = contract(
487
534
  is.fun([], is.or(is.class("State"), is.eq(undefined))),
488
535
  () => {
@@ -497,14 +544,17 @@ const getState = contract(
497
544
  var tenants = { public: singleton };
498
545
  // list of tenants with other domains
499
546
  const otherdomaintenants = {};
547
+
500
548
  /**
501
549
  * Get other domain tenant
502
- * @param hostname
550
+ * @param {string} hostname
551
+ * @returns {object}
503
552
  */
504
553
  const get_other_domain_tenant = (hostname) => otherdomaintenants[hostname];
505
554
  /**
506
555
  * Get tenant
507
- * @param ten
556
+ * @param {string} ten
557
+ * @returns {object}
508
558
  */
509
559
  const getTenant = (ten) => {
510
560
  //console.log({ ten, tenants });
@@ -512,8 +562,8 @@ const getTenant = (ten) => {
512
562
  };
513
563
  /**
514
564
  * Remove protocol (http:// or https://) from domain url
515
- * @param url
516
- * @returns {*}
565
+ * @param {string} url
566
+ * @returns {string}
517
567
  */
518
568
  const get_domain = (url) => {
519
569
  const noproto = url.replace("https://", "").replace("http://", "");
@@ -522,8 +572,8 @@ const get_domain = (url) => {
522
572
  /**
523
573
  * Set tenant base url???
524
574
  * From my point of view it just add tenant to list of otherdomaintenant
525
- * @param tenant_subdomain
526
- * @param value - new
575
+ * @param {object} tenant_subdomain
576
+ * @param {string} [value] - new
527
577
  */
528
578
  const set_tenant_base_url = (tenant_subdomain, value) => {
529
579
  const root_domain = get_domain(singleton.configs.base_url.value);
@@ -535,8 +585,8 @@ const set_tenant_base_url = (tenant_subdomain, value) => {
535
585
  };
536
586
  /**
537
587
  * Switch to multi_tenant
538
- * @param plugin_loader
539
- * @param disableMigrate - if true then dont migrate db
588
+ * @param {object} plugin_loader
589
+ * @param {boolean} disableMigrate - if true then dont migrate db
540
590
  * @returns {Promise<void>}
541
591
  */
542
592
  const init_multi_tenant = async (plugin_loader, disableMigrate) => {
@@ -558,20 +608,39 @@ const init_multi_tenant = async (plugin_loader, disableMigrate) => {
558
608
  };
559
609
  /**
560
610
  * Create tenant
561
- * @param t
562
- * @param plugin_loader
563
- * @param newurl
611
+ * @param {string} t
612
+ * @param {object} plugin_loader
613
+ * @param {string} newurl
614
+ * @param {boolean} noSignalOrDB
564
615
  * @returns {Promise<void>}
565
616
  */
566
- const create_tenant = async (t, plugin_loader, newurl, noSignalOrDB) => {
617
+ const create_tenant = async (
618
+ t,
619
+ plugin_loader,
620
+ newurl,
621
+ noSignalOrDB,
622
+ loadAndSaveNewPlugin
623
+ ) => {
567
624
  if (!noSignalOrDB) await createTenant(t, newurl);
568
625
  tenants[t] = new State(t);
569
626
  await db.runWithTenant(t, plugin_loader);
570
- if (!noSignalOrDB) process_send({ createTenant: t });
627
+ if (!noSignalOrDB) {
628
+ const tenant_template = singleton.getConfig("tenant_template");
629
+ if (tenant_template) {
630
+ //create backup
631
+ await copy_tenant_template({
632
+ tenant_template,
633
+ target: t,
634
+ state: tenants[t],
635
+ loadAndSaveNewPlugin,
636
+ });
637
+ }
638
+ process_send({ createTenant: t });
639
+ }
571
640
  };
572
641
  /**
573
642
  * Restart tenant
574
- * @param plugin_loader
643
+ * @param {object} plugin_loader
575
644
  * @returns {Promise<void>}
576
645
  */
577
646
  const restart_tenant = async (plugin_loader) => {
package/index.js CHANGED
@@ -1 +1,14 @@
1
+ /**
2
+ * @category saltcorn-data
3
+ * @module saltcorn-data/index
4
+ */
5
+
6
+ /**
7
+ * All modules in the saltcorn-data package.
8
+ * @namespace saltcorn-data_overview
9
+ * @property {module:models/index~models_overview} models
10
+ * @property {module:db/index~db_overview} db
11
+ * @property {module:base-plugin/index~base-plugin_overview} base-plugin
12
+ * @category saltcorn-data
13
+ */
1
14
  module.exports = {};