@saltcorn/server 0.9.5-beta.1 → 0.9.5-beta.11
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/auth/admin.js +7 -0
- package/auth/routes.js +7 -3
- package/errors.js +1 -0
- package/help/Cordova Builder.tmd +13 -0
- package/load_plugins.js +83 -144
- package/locales/en.json +9 -2
- package/package.json +16 -13
- package/public/flatpickr.min.js +2 -2
- package/public/log_viewer_utils.js +17 -1
- package/public/saltcorn-common.js +33 -11
- package/public/saltcorn.js +51 -3
- package/restart_watcher.js +1 -0
- package/routes/admin.js +149 -3
- package/routes/common_lists.js +1 -1
- package/routes/fields.js +9 -7
- package/routes/homepage.js +6 -3
- package/routes/pageedit.js +1 -1
- package/routes/plugins.js +10 -1
- package/routes/tables.js +4 -0
- package/serve.js +1 -1
- package/tests/page.test.js +11 -1
package/auth/admin.js
CHANGED
|
@@ -82,6 +82,13 @@ const getUserFields = async (req) => {
|
|
|
82
82
|
await iterForm("new_user_form");
|
|
83
83
|
//console.log(userFields);
|
|
84
84
|
for (const f of userFields) {
|
|
85
|
+
if (f.is_fkey && !f.fieldview) {
|
|
86
|
+
f.fieldviewObj = getState().keyFieldviews?.select;
|
|
87
|
+
if (f.fieldviewObj) {
|
|
88
|
+
f.input_type = "fromtype";
|
|
89
|
+
f.fieldview = "select";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
85
92
|
await f.fill_fkey_options();
|
|
86
93
|
if (f.name === "email") {
|
|
87
94
|
f.validator = (s) => {
|
package/auth/routes.js
CHANGED
|
@@ -514,9 +514,13 @@ router.get(
|
|
|
514
514
|
if (!signup_form) await defaultSignup();
|
|
515
515
|
else {
|
|
516
516
|
const resp = await signup_form.run_possibly_on_page({}, req, res);
|
|
517
|
-
if (signup_form.default_render_page)
|
|
518
|
-
|
|
519
|
-
|
|
517
|
+
if (signup_form.default_render_page) {
|
|
518
|
+
const page = Page.findOne({ name: signup_form.default_render_page });
|
|
519
|
+
res.sendWrap(
|
|
520
|
+
{ title: req.__(`Sign up`), no_menu: page?.attributes?.no_menu },
|
|
521
|
+
resp
|
|
522
|
+
);
|
|
523
|
+
} else res.sendAuthWrap(req.__(`Sign up`), resp, { methods: [] });
|
|
520
524
|
}
|
|
521
525
|
} else await defaultSignup();
|
|
522
526
|
})
|
package/errors.js
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
The Cordova builder is a docker image with all dependencies to build Android apps.
|
|
2
|
+
It can be pulled from dockerhub while installing Saltcorn, or you can use the pull button.
|
|
3
|
+
|
|
4
|
+
Please make sure your server has a valid and accessible docker daemon running.
|
|
5
|
+
|
|
6
|
+
For this, either set up a standard docker installation
|
|
7
|
+
or use the [docker rootless mode](https://docs.docker.com/engine/security/rootless/) (recommended).
|
|
8
|
+
|
|
9
|
+
In a standard docker environment, you need root user privileges.
|
|
10
|
+
For this, you can add the user running Saltcorn to the docker group,
|
|
11
|
+
or if you already have the privileges, you are ready to go.
|
|
12
|
+
|
|
13
|
+
A docker daemon in rootless mode doesn't need any further configuration.
|
package/load_plugins.js
CHANGED
|
@@ -6,59 +6,10 @@
|
|
|
6
6
|
* @module load_plugins
|
|
7
7
|
*/
|
|
8
8
|
const db = require("@saltcorn/data/db");
|
|
9
|
-
const { PluginManager } = require("live-plugin-manager");
|
|
10
9
|
const { getState, getRootState } = require("@saltcorn/data/db/state");
|
|
11
10
|
const Plugin = require("@saltcorn/data/models/plugin");
|
|
12
|
-
const fs = require("fs");
|
|
13
|
-
const proc = require("child_process");
|
|
14
|
-
const tmp = require("tmp-promise");
|
|
15
11
|
|
|
16
|
-
const
|
|
17
|
-
"@saltcorn/markup": require("@saltcorn/markup"),
|
|
18
|
-
"@saltcorn/markup/tags": require("@saltcorn/markup/tags"),
|
|
19
|
-
"@saltcorn/markup/layout": require("@saltcorn/markup/layout"),
|
|
20
|
-
"@saltcorn/markup/helpers": require("@saltcorn/markup/helpers"),
|
|
21
|
-
"@saltcorn/markup/layout_utils": require("@saltcorn/markup/layout_utils"),
|
|
22
|
-
"@saltcorn/data": require("@saltcorn/data"),
|
|
23
|
-
"@saltcorn/data/db": require("@saltcorn/data/db"),
|
|
24
|
-
"@saltcorn/data/utils": require("@saltcorn/data/utils"),
|
|
25
|
-
"@saltcorn/data/db/state": require("@saltcorn/data/db/state"),
|
|
26
|
-
"@saltcorn/data/plugin-helper": require("@saltcorn/data/plugin-helper"),
|
|
27
|
-
"@saltcorn/data/plugin-testing": require("@saltcorn/data/plugin-testing"),
|
|
28
|
-
"@saltcorn/data/models/field": require("@saltcorn/data/models/field"),
|
|
29
|
-
"@saltcorn/data/models/fieldrepeat": require("@saltcorn/data/models/fieldrepeat"),
|
|
30
|
-
"@saltcorn/data/models/table": require("@saltcorn/data/models/table"),
|
|
31
|
-
"@saltcorn/data/models/form": require("@saltcorn/data/models/form"),
|
|
32
|
-
"@saltcorn/data/models/discovery": require("@saltcorn/data/models/discovery"),
|
|
33
|
-
"@saltcorn/data/models/config": require("@saltcorn/data/models/config"),
|
|
34
|
-
"@saltcorn/data/models/library": require("@saltcorn/data/models/library"),
|
|
35
|
-
"@saltcorn/data/models/model": require("@saltcorn/data/models/model"),
|
|
36
|
-
"@saltcorn/data/models/model_instance": require("@saltcorn/data/models/model_instance"),
|
|
37
|
-
"@saltcorn/data/models/notification": require("@saltcorn/data/models/notification"),
|
|
38
|
-
"@saltcorn/data/models/role": require("@saltcorn/data/models/role"),
|
|
39
|
-
"@saltcorn/data/models/tag": require("@saltcorn/data/models/tag"),
|
|
40
|
-
"@saltcorn/data/models/tag_entry": require("@saltcorn/data/models/tag_entry"),
|
|
41
|
-
"@saltcorn/data/models/view": require("@saltcorn/data/models/view"),
|
|
42
|
-
"@saltcorn/data/models/page": require("@saltcorn/data/models/page"),
|
|
43
|
-
"@saltcorn/data/models/file": require("@saltcorn/data/models/file"),
|
|
44
|
-
"@saltcorn/data/models/user": require("@saltcorn/data/models/user"),
|
|
45
|
-
"@saltcorn/data/models/layout": require("@saltcorn/data/models/layout"),
|
|
46
|
-
"@saltcorn/data/models/expression": require("@saltcorn/data/models/expression"),
|
|
47
|
-
"@saltcorn/data/models/workflow": require("@saltcorn/data/models/workflow"),
|
|
48
|
-
imapflow: require("imapflow"),
|
|
49
|
-
"node-fetch": require("node-fetch"),
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Create plugin manager with default list of core plugins
|
|
54
|
-
* @type {PluginManager}
|
|
55
|
-
*/
|
|
56
|
-
const defaultManager = new PluginManager({
|
|
57
|
-
staticDependencies: {
|
|
58
|
-
contractis: require("contractis"),
|
|
59
|
-
...staticDependencies,
|
|
60
|
-
},
|
|
61
|
-
});
|
|
12
|
+
const PluginInstaller = require("@saltcorn/plugins-loader/plugin_installer");
|
|
62
13
|
|
|
63
14
|
/**
|
|
64
15
|
* Load one plugin
|
|
@@ -68,19 +19,35 @@ const defaultManager = new PluginManager({
|
|
|
68
19
|
*/
|
|
69
20
|
const loadPlugin = async (plugin, force) => {
|
|
70
21
|
// load plugin
|
|
71
|
-
const
|
|
22
|
+
const loader = new PluginInstaller(plugin);
|
|
23
|
+
const res = await loader.install(force);
|
|
72
24
|
const configuration =
|
|
73
25
|
typeof plugin.configuration === "string"
|
|
74
26
|
? JSON.parse(plugin.configuration)
|
|
75
27
|
: plugin.configuration;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
28
|
+
try {
|
|
29
|
+
// register plugin
|
|
30
|
+
getState().registerPlugin(
|
|
31
|
+
res.plugin_module.plugin_name || plugin.name,
|
|
32
|
+
res.plugin_module,
|
|
33
|
+
configuration,
|
|
34
|
+
res.location,
|
|
35
|
+
res.name
|
|
36
|
+
);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (force) {
|
|
39
|
+
// remove the install dir and try again
|
|
40
|
+
await loader.remove();
|
|
41
|
+
await loader.install(force);
|
|
42
|
+
getState().registerPlugin(
|
|
43
|
+
res.plugin_module.plugin_name || plugin.name,
|
|
44
|
+
res.plugin_module,
|
|
45
|
+
configuration,
|
|
46
|
+
res.location,
|
|
47
|
+
res.name
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
84
51
|
if (res.plugin_module.onLoad) {
|
|
85
52
|
try {
|
|
86
53
|
await res.plugin_module.onLoad(plugin.configuration);
|
|
@@ -91,105 +58,48 @@ const loadPlugin = async (plugin, force) => {
|
|
|
91
58
|
return res;
|
|
92
59
|
};
|
|
93
60
|
|
|
94
|
-
/**
|
|
95
|
-
* Git pull or clone
|
|
96
|
-
* @param plugin
|
|
97
|
-
*/
|
|
98
|
-
const gitPullOrClone = async (plugin) => {
|
|
99
|
-
await fs.promises.mkdir("git_plugins", { recursive: true });
|
|
100
|
-
let keyfnm,
|
|
101
|
-
setKey = `-c core.sshCommand="ssh -oBatchMode=yes -o 'StrictHostKeyChecking no'" `;
|
|
102
|
-
if (plugin.deploy_private_key) {
|
|
103
|
-
keyfnm = await tmp.tmpName();
|
|
104
|
-
await fs.promises.writeFile(
|
|
105
|
-
keyfnm,
|
|
106
|
-
plugin.deploy_private_key.replace(/[\r]+/g, "") + "\n",
|
|
107
|
-
{
|
|
108
|
-
mode: 0o600,
|
|
109
|
-
encoding: "ascii",
|
|
110
|
-
}
|
|
111
|
-
);
|
|
112
|
-
setKey = `-c core.sshCommand="ssh -oBatchMode=yes -o 'StrictHostKeyChecking no' -i ${keyfnm}" `;
|
|
113
|
-
}
|
|
114
|
-
const dir = `git_plugins/${plugin.name}`;
|
|
115
|
-
if (fs.existsSync(dir)) {
|
|
116
|
-
proc.execSync(`git ${setKey} -C ${dir} pull`);
|
|
117
|
-
} else {
|
|
118
|
-
proc.execSync(`git ${setKey} clone ${plugin.location} ${dir}`);
|
|
119
|
-
}
|
|
120
|
-
if (plugin.deploy_private_key) await fs.promises.unlink(keyfnm);
|
|
121
|
-
return dir;
|
|
122
|
-
};
|
|
123
61
|
/**
|
|
124
62
|
* Install plugin
|
|
125
63
|
* @param plugin - plugin name
|
|
126
64
|
* @param force - force flag
|
|
127
|
-
* @param manager - plugin manager
|
|
128
65
|
* @returns {Promise<{plugin_module: *}|{plugin_module: any}>}
|
|
129
66
|
*/
|
|
130
|
-
const requirePlugin = async (plugin, force
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
if (
|
|
134
|
-
["@saltcorn/base-plugin", "@saltcorn/sbadmin2"].includes(plugin.location)
|
|
135
|
-
) {
|
|
136
|
-
return { plugin_module: require(plugin.location) };
|
|
137
|
-
} else if (plugin.source === "npm") {
|
|
138
|
-
if (force || !installed_plugins.includes(plugin.location)) {
|
|
139
|
-
const plinfo = await manager.install(plugin.location, plugin.version);
|
|
140
|
-
return { plugin_module: manager.require(plugin.location), ...plinfo };
|
|
141
|
-
} else {
|
|
142
|
-
const plinfo = manager.getInfo(plugin.location);
|
|
143
|
-
return { plugin_module: manager.require(plugin.location), ...plinfo };
|
|
144
|
-
}
|
|
145
|
-
} else if (plugin.source === "local") {
|
|
146
|
-
const plinfo = await manager.installFromPath(plugin.location, {
|
|
147
|
-
force: true,
|
|
148
|
-
});
|
|
149
|
-
return { plugin_module: manager.require(plugin.name), ...plinfo };
|
|
150
|
-
} else if (plugin.source === "git") {
|
|
151
|
-
const loc = await gitPullOrClone(plugin);
|
|
152
|
-
const plinfo = await manager.installFromPath(loc, {
|
|
153
|
-
force: true,
|
|
154
|
-
});
|
|
155
|
-
return { plugin_module: manager.require(plugin.name), ...plinfo };
|
|
156
|
-
} else if (plugin.source === "github") {
|
|
157
|
-
if (force || !installed_plugins.includes(plugin.location)) {
|
|
158
|
-
const plinfo = await manager.installFromGithub(plugin.location, {
|
|
159
|
-
force: true,
|
|
160
|
-
});
|
|
161
|
-
return { plugin_module: manager.require(plugin.name), ...plinfo };
|
|
162
|
-
} else {
|
|
163
|
-
const plinfo = manager.getInfo(plugin.location);
|
|
164
|
-
return { plugin_module: manager.require(plugin.location), ...plinfo };
|
|
165
|
-
}
|
|
166
|
-
} else throw new Error("Unknown plugin source: " + plugin.source);
|
|
67
|
+
const requirePlugin = async (plugin, force) => {
|
|
68
|
+
const loader = new PluginInstaller(plugin);
|
|
69
|
+
return await loader.install(force);
|
|
167
70
|
};
|
|
71
|
+
|
|
168
72
|
/**
|
|
169
73
|
* Load all plugins
|
|
170
74
|
* @returns {Promise<void>}
|
|
171
75
|
*/
|
|
172
|
-
const loadAllPlugins = async () => {
|
|
76
|
+
const loadAllPlugins = async (force) => {
|
|
173
77
|
await getState().refresh(true);
|
|
174
78
|
const plugins = await db.select("_sc_plugins");
|
|
175
79
|
for (const plugin of plugins) {
|
|
176
80
|
try {
|
|
177
|
-
await loadPlugin(plugin);
|
|
81
|
+
await loadPlugin(plugin, force);
|
|
178
82
|
} catch (e) {
|
|
179
83
|
console.error(e);
|
|
180
84
|
}
|
|
181
85
|
}
|
|
182
86
|
await getState().refresh(true);
|
|
183
87
|
};
|
|
88
|
+
|
|
184
89
|
/**
|
|
185
90
|
* Load Plugin and its dependencies and save into local installation
|
|
186
91
|
* @param plugin
|
|
187
92
|
* @param force
|
|
188
93
|
* @param noSignalOrDB
|
|
189
|
-
* @param
|
|
94
|
+
* @param __ translation function
|
|
190
95
|
* @returns {Promise<void>}
|
|
191
96
|
*/
|
|
192
|
-
const loadAndSaveNewPlugin = async (
|
|
97
|
+
const loadAndSaveNewPlugin = async (
|
|
98
|
+
plugin,
|
|
99
|
+
force,
|
|
100
|
+
noSignalOrDB,
|
|
101
|
+
__ = (str) => str
|
|
102
|
+
) => {
|
|
193
103
|
const tenants_unsafe_plugins = getRootState().getConfig(
|
|
194
104
|
"tenants_unsafe_plugins",
|
|
195
105
|
false
|
|
@@ -215,11 +125,10 @@ const loadAndSaveNewPlugin = async (plugin, force, noSignalOrDB, manager) => {
|
|
|
215
125
|
return;
|
|
216
126
|
}
|
|
217
127
|
}
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
);
|
|
128
|
+
const msgs = [];
|
|
129
|
+
const loader = new PluginInstaller(plugin);
|
|
130
|
+
const { version, plugin_module, location, loadedWithReload } =
|
|
131
|
+
await loader.install(force);
|
|
223
132
|
|
|
224
133
|
// install dependecies
|
|
225
134
|
for (const loc of plugin_module.dependencies || []) {
|
|
@@ -232,13 +141,43 @@ const loadAndSaveNewPlugin = async (plugin, force, noSignalOrDB, manager) => {
|
|
|
232
141
|
);
|
|
233
142
|
}
|
|
234
143
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
144
|
+
let registeredWithReload = false;
|
|
145
|
+
try {
|
|
146
|
+
getState().registerPlugin(
|
|
147
|
+
plugin_module.plugin_name || plugin.name,
|
|
148
|
+
plugin_module,
|
|
149
|
+
plugin.configuration,
|
|
150
|
+
location,
|
|
151
|
+
plugin.name
|
|
152
|
+
);
|
|
153
|
+
} catch (error) {
|
|
154
|
+
if (force) {
|
|
155
|
+
getState().log(
|
|
156
|
+
2,
|
|
157
|
+
`Error registering plugin ${plugin.name}. Removing and trying again.`
|
|
158
|
+
);
|
|
159
|
+
await loader.remove();
|
|
160
|
+
await loader.install(force);
|
|
161
|
+
getState().registerPlugin(
|
|
162
|
+
plugin_module.plugin_name || plugin.name,
|
|
163
|
+
plugin_module,
|
|
164
|
+
plugin.configuration,
|
|
165
|
+
location,
|
|
166
|
+
plugin.name
|
|
167
|
+
);
|
|
168
|
+
registeredWithReload = true;
|
|
169
|
+
} else {
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (loadedWithReload || registeredWithReload) {
|
|
174
|
+
msgs.push(
|
|
175
|
+
__(
|
|
176
|
+
"The plugin was corrupted and had to be repaired. We recommend restarting your server.",
|
|
177
|
+
plugin.name
|
|
178
|
+
)
|
|
179
|
+
);
|
|
180
|
+
}
|
|
242
181
|
if (plugin_module.onLoad) {
|
|
243
182
|
try {
|
|
244
183
|
await plugin_module.onLoad(plugin.configuration);
|
|
@@ -252,9 +191,10 @@ const loadAndSaveNewPlugin = async (plugin, force, noSignalOrDB, manager) => {
|
|
|
252
191
|
getState().processSend({
|
|
253
192
|
installPlugin: plugin,
|
|
254
193
|
tenant: db.getTenantSchema(),
|
|
255
|
-
force,
|
|
194
|
+
force: false, // okay ??
|
|
256
195
|
});
|
|
257
196
|
}
|
|
197
|
+
return msgs;
|
|
258
198
|
};
|
|
259
199
|
|
|
260
200
|
module.exports = {
|
|
@@ -262,5 +202,4 @@ module.exports = {
|
|
|
262
202
|
loadAllPlugins,
|
|
263
203
|
loadPlugin,
|
|
264
204
|
requirePlugin,
|
|
265
|
-
staticDependencies,
|
|
266
205
|
};
|
package/locales/en.json
CHANGED
|
@@ -1384,5 +1384,12 @@
|
|
|
1384
1384
|
"Optionally associate a table with this trigger": "Optionally associate a table with this trigger",
|
|
1385
1385
|
"Delete table": "Delete table",
|
|
1386
1386
|
"Signup role": "Signup role",
|
|
1387
|
-
"The initial role of signed up users": "The initial role of signed up users"
|
|
1388
|
-
|
|
1387
|
+
"The initial role of signed up users": "The initial role of signed up users",
|
|
1388
|
+
"Cordova builder": "Cordova builder",
|
|
1389
|
+
"not available": "not available",
|
|
1390
|
+
"pull": "pull",
|
|
1391
|
+
"refresh": "refresh",
|
|
1392
|
+
"installed": "installed",
|
|
1393
|
+
"Include table history in backup": "Include table history in backup",
|
|
1394
|
+
"The plugin was corrupted and had to be repaired. We recommend restarting your server.": "The plugin was corrupted and had to be repaired. We recommend restarting your server."
|
|
1395
|
+
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "0.9.5-beta.
|
|
3
|
+
"version": "0.9.5-beta.11",
|
|
4
4
|
"description": "Server app for Saltcorn, open-source no-code platform",
|
|
5
5
|
"homepage": "https://saltcorn.com",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@aws-sdk/client-s3": "^3.451.0",
|
|
10
|
-
"@saltcorn/base-plugin": "0.9.5-beta.
|
|
11
|
-
"@saltcorn/builder": "0.9.5-beta.
|
|
12
|
-
"@saltcorn/data": "0.9.5-beta.
|
|
13
|
-
"@saltcorn/admin-models": "0.9.5-beta.
|
|
14
|
-
"@saltcorn/filemanager": "0.9.5-beta.
|
|
15
|
-
"@saltcorn/markup": "0.9.5-beta.
|
|
16
|
-
"@saltcorn/
|
|
10
|
+
"@saltcorn/base-plugin": "0.9.5-beta.11",
|
|
11
|
+
"@saltcorn/builder": "0.9.5-beta.11",
|
|
12
|
+
"@saltcorn/data": "0.9.5-beta.11",
|
|
13
|
+
"@saltcorn/admin-models": "0.9.5-beta.11",
|
|
14
|
+
"@saltcorn/filemanager": "0.9.5-beta.11",
|
|
15
|
+
"@saltcorn/markup": "0.9.5-beta.11",
|
|
16
|
+
"@saltcorn/plugins-loader": "0.9.5-beta.11",
|
|
17
|
+
"@saltcorn/sbadmin2": "0.9.5-beta.11",
|
|
17
18
|
"@socket.io/cluster-adapter": "^0.2.1",
|
|
18
19
|
"@socket.io/sticky": "^1.0.1",
|
|
19
20
|
"adm-zip": "0.5.10",
|
|
@@ -26,6 +27,7 @@
|
|
|
26
27
|
"cors": "2.8.5",
|
|
27
28
|
"csurf": "^1.11.0",
|
|
28
29
|
"csv-stringify": "^5.5.0",
|
|
30
|
+
"dockerode": "~4.0.2",
|
|
29
31
|
"express": "^4.17.1",
|
|
30
32
|
"express-fileupload": "^1.1.8",
|
|
31
33
|
"express-promise-router": "^3.0.3",
|
|
@@ -37,7 +39,6 @@
|
|
|
37
39
|
"i18n": "^0.15.1",
|
|
38
40
|
"imapflow": "1.0.123",
|
|
39
41
|
"jsonwebtoken": "^9.0.0",
|
|
40
|
-
"live-plugin-manager": "^0.17.1",
|
|
41
42
|
"markdown-it": "^13.0.2",
|
|
42
43
|
"moment": "^2.29.4",
|
|
43
44
|
"multer": "1.4.5-lts.1",
|
|
@@ -70,8 +71,8 @@
|
|
|
70
71
|
},
|
|
71
72
|
"repository": "github:saltcorn/saltcorn",
|
|
72
73
|
"devDependencies": {
|
|
73
|
-
"jest": "
|
|
74
|
-
"jest-environment-jsdom": "
|
|
74
|
+
"jest": "^28.1.3",
|
|
75
|
+
"jest-environment-jsdom": "28.1.3",
|
|
75
76
|
"supertest": "^6.3.3"
|
|
76
77
|
},
|
|
77
78
|
"scripts": {
|
|
@@ -84,11 +85,13 @@
|
|
|
84
85
|
"testEnvironment": "node",
|
|
85
86
|
"testPathIgnorePatterns": [
|
|
86
87
|
"/node_modules/",
|
|
87
|
-
"/plugin_packages/"
|
|
88
|
+
"/plugin_packages/",
|
|
89
|
+
"/plugins_folder/"
|
|
88
90
|
],
|
|
89
91
|
"coveragePathIgnorePatterns": [
|
|
90
92
|
"/node_modules/",
|
|
91
|
-
"/plugin_packages/"
|
|
93
|
+
"/plugin_packages/",
|
|
94
|
+
"/plugins_folder/"
|
|
92
95
|
],
|
|
93
96
|
"moduleNameMapper": {
|
|
94
97
|
"@saltcorn/sqlite/(.*)": "<rootDir>/../sqlite/dist/$1",
|