@saltcorn/server 0.6.1 → 0.6.2-beta.0
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/index.js +15 -2
- package/index.js +17 -1
- package/markup/index.js +14 -1
- package/package.json +14 -8
- package/public/saltcorn.js +12 -0
- package/restart_watcher.js +146 -0
- package/routes/fields.js +13 -13
- package/routes/index.js +37 -0
- package/routes/view.js +4 -4
- package/serve.js +10 -2
package/auth/index.js
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
/**
|
|
3
3
|
*
|
|
4
4
|
* @category server
|
|
5
|
-
* @module auth/
|
|
5
|
+
* @module auth/index
|
|
6
6
|
* @subcategory auth
|
|
7
|
-
*/
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* All files in the auth module.
|
|
11
|
+
* @namespace auth_overview
|
|
12
|
+
* @property {module:auth/admin} admin
|
|
13
|
+
* @property {module:auth/resetpw} resetpw
|
|
14
|
+
* @property {module:auth/roleadmin} roleadmin
|
|
15
|
+
* @property {module:auth/routes} routes
|
|
16
|
+
* @property {module:auth/testhelp} testhelp
|
|
17
|
+
*
|
|
18
|
+
* @category server
|
|
19
|
+
* @subcategory auth
|
|
20
|
+
*/
|
package/index.js
CHANGED
|
@@ -3,4 +3,20 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @category server
|
|
5
5
|
* @module server/index
|
|
6
|
-
*/
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* All files and sub-modules in the saltcorn-markup package.
|
|
10
|
+
* @namespace server_overview
|
|
11
|
+
* @property {module:auth/index~auth_overview} auth
|
|
12
|
+
* @property {module:markup/index~markup_overview} markup
|
|
13
|
+
* @property {module:routes/index~routes_overview} routes
|
|
14
|
+
*
|
|
15
|
+
* @property {module:app} app
|
|
16
|
+
* @property {module:errors} errors
|
|
17
|
+
* @property {module:load_plugins} load_plugins
|
|
18
|
+
* @property {module:serve} serve
|
|
19
|
+
* @property {module:systemd} systemd
|
|
20
|
+
* @property {module:wrapper} wrapper
|
|
21
|
+
* @category server
|
|
22
|
+
*/
|
package/markup/index.js
CHANGED
|
@@ -4,4 +4,17 @@
|
|
|
4
4
|
* @category server
|
|
5
5
|
* @module markup/index
|
|
6
6
|
* @subcategory markup
|
|
7
|
-
*/
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* All files in the auth module.
|
|
11
|
+
* @namespace markup_overview
|
|
12
|
+
* @property {module:markup/admin} admin
|
|
13
|
+
* @property {module:markup/blockly} blockly
|
|
14
|
+
* @property {module:markup/expression_blurb} expression_blurb
|
|
15
|
+
* @property {module:markup/forms} forms
|
|
16
|
+
* @property {module:markup/plugin-store} plugin-store
|
|
17
|
+
*
|
|
18
|
+
* @category server
|
|
19
|
+
* @subcategory markup
|
|
20
|
+
*/
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2-beta.0",
|
|
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
|
-
"@saltcorn/base-plugin": "0.6.
|
|
10
|
-
"@saltcorn/builder": "0.6.
|
|
11
|
-
"@saltcorn/data": "0.6.
|
|
9
|
+
"@saltcorn/base-plugin": "0.6.2-beta.0",
|
|
10
|
+
"@saltcorn/builder": "0.6.2-beta.0",
|
|
11
|
+
"@saltcorn/data": "0.6.2-beta.0",
|
|
12
12
|
"greenlock-express": "^4.0.3",
|
|
13
|
-
"@saltcorn/markup": "0.6.
|
|
14
|
-
"@saltcorn/sbadmin2": "0.6.
|
|
13
|
+
"@saltcorn/markup": "0.6.2-beta.0",
|
|
14
|
+
"@saltcorn/sbadmin2": "0.6.2-beta.0",
|
|
15
15
|
"@socket.io/cluster-adapter": "^0.1.0",
|
|
16
16
|
"@socket.io/sticky": "^1.0.1",
|
|
17
17
|
"connect-flash": "^0.1.1",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"live-plugin-manager": "^0.16.0",
|
|
34
34
|
"moment": "^2.27.0",
|
|
35
35
|
"node-fetch": "2.6.2",
|
|
36
|
+
"node-watch": "^0.7.2",
|
|
36
37
|
"passport": "^0.4.1",
|
|
37
38
|
"passport-custom": "^1.1.1",
|
|
38
39
|
"passport-http-bearer": "^1.0.1",
|
|
@@ -51,7 +52,9 @@
|
|
|
51
52
|
},
|
|
52
53
|
"scripts": {
|
|
53
54
|
"dev": "nodemon index.js",
|
|
54
|
-
"test": "jest --runInBand"
|
|
55
|
+
"test": "jest --runInBand",
|
|
56
|
+
"tsc": "echo \"Error: no TypeScript support yet\"",
|
|
57
|
+
"clean": "echo \"Error: no TypeScript support yet\""
|
|
55
58
|
},
|
|
56
59
|
"jest": {
|
|
57
60
|
"testEnvironment": "node",
|
|
@@ -62,7 +65,10 @@
|
|
|
62
65
|
"coveragePathIgnorePatterns": [
|
|
63
66
|
"/node_modules/",
|
|
64
67
|
"/plugin_packages/"
|
|
65
|
-
]
|
|
68
|
+
],
|
|
69
|
+
"moduleNameMapper": {
|
|
70
|
+
"@saltcorn/sqlite/(.*)": "@saltcorn/sqlite/dist/$1"
|
|
71
|
+
}
|
|
66
72
|
},
|
|
67
73
|
"publishConfig": {
|
|
68
74
|
"access": "public"
|
package/public/saltcorn.js
CHANGED
|
@@ -306,6 +306,18 @@ function select_id(id) {
|
|
|
306
306
|
function set_state_field(key, value) {
|
|
307
307
|
pjax_to(updateQueryStringParameter(window.location.href, key, value));
|
|
308
308
|
}
|
|
309
|
+
|
|
310
|
+
function check_state_field(that) {
|
|
311
|
+
const checked = that.checked;
|
|
312
|
+
const name = that.name;
|
|
313
|
+
const value = that.value;
|
|
314
|
+
var separator = window.location.href.indexOf("?") !== -1 ? "&" : "?";
|
|
315
|
+
let dest;
|
|
316
|
+
if (checked) dest = window.location.href + `${separator}${name}=${value}`;
|
|
317
|
+
else dest = window.location.href.replace(`${name}=${value}`, "");
|
|
318
|
+
pjax_to(dest.replace("&&", "&").replace("?&", "?"));
|
|
319
|
+
}
|
|
320
|
+
|
|
309
321
|
function set_state_fields(kvs) {
|
|
310
322
|
var newhref = window.location.href;
|
|
311
323
|
Object.entries(kvs).forEach((kv) => {
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @category server
|
|
3
|
+
* @module restart_watcher
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const { spawnSync } = require("child_process");
|
|
8
|
+
const watch = require("node-watch");
|
|
9
|
+
const Plugin = require("@saltcorn/data/models/plugin");
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* packages that should trigger a server re-start
|
|
13
|
+
*/
|
|
14
|
+
const relevantPackages = [
|
|
15
|
+
"db-common",
|
|
16
|
+
"postgres",
|
|
17
|
+
"saltcorn-data",
|
|
18
|
+
"saltcorn-markup",
|
|
19
|
+
"server",
|
|
20
|
+
"sqlite",
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* excluded directories or file name patterns
|
|
25
|
+
*/
|
|
26
|
+
const excludePatterns = [
|
|
27
|
+
/\/node_modules/,
|
|
28
|
+
/\/public/,
|
|
29
|
+
/\.git/,
|
|
30
|
+
/\.docs/,
|
|
31
|
+
/\.docs/,
|
|
32
|
+
/\migrations/,
|
|
33
|
+
/.*test.js/,
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* get the root directory of the saltcorn project
|
|
38
|
+
* @returns {string} project root path
|
|
39
|
+
*/
|
|
40
|
+
const getProjectRoot = () => {
|
|
41
|
+
return path.normalize(`${__dirname}/../../`);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* get the packages directory of the saltcorn project
|
|
46
|
+
* @returns {string} packages path
|
|
47
|
+
*/
|
|
48
|
+
const getPackagesDirectory = () => {
|
|
49
|
+
return `${getProjectRoot()}/packages`;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* get all package directories that should trigger a server re-start
|
|
54
|
+
* @returns {string[]} list of paths to relevant directories
|
|
55
|
+
*/
|
|
56
|
+
const getRelevantPackages = () => {
|
|
57
|
+
const packagesDir = getPackagesDirectory();
|
|
58
|
+
return relevantPackages.map((packageName) => `${packagesDir}/${packageName}`);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* get all plugin directories that should trigger a server re-start
|
|
63
|
+
* @returns {string[]} list of paths to relevant directories
|
|
64
|
+
*/
|
|
65
|
+
const getPluginDirectories = async () => {
|
|
66
|
+
const local_plugins = await Plugin.find({ source: "local" });
|
|
67
|
+
return local_plugins.map((p) => p.location);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const projectRoot = getProjectRoot();
|
|
71
|
+
|
|
72
|
+
const watchCfg = {
|
|
73
|
+
recursive: true,
|
|
74
|
+
filter(file, skip) {
|
|
75
|
+
for (const excludePattern of excludePatterns) {
|
|
76
|
+
if (excludePattern.test(file)) return skip;
|
|
77
|
+
}
|
|
78
|
+
return /(\.js|\.ts)$/.test(file);
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
let activeWatchers = [];
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* close all open file watchers
|
|
86
|
+
*/
|
|
87
|
+
const closeWatchers = () => {
|
|
88
|
+
for (const activeWatcher of activeWatchers) {
|
|
89
|
+
if (!activeWatcher.isClosed()) {
|
|
90
|
+
activeWatcher.close();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* register many file change listener and do re-starts on changes
|
|
97
|
+
* The listener calls process.exit() and assumes
|
|
98
|
+
* that pm2 does the actual re-start.
|
|
99
|
+
* @param {string[]} projectDirs package paths that should trigger re-starts.
|
|
100
|
+
* @param {string[]} pluginDirs plugin paths that should trigger re-starts.
|
|
101
|
+
*/
|
|
102
|
+
const listenForChanges = (projectDirs, pluginDirs) => {
|
|
103
|
+
// watch project dirs
|
|
104
|
+
for (const projectDir of projectDirs) {
|
|
105
|
+
activeWatchers.push(
|
|
106
|
+
watch(
|
|
107
|
+
projectDir,
|
|
108
|
+
watchCfg,
|
|
109
|
+
// event is either 'update' or 'remove'
|
|
110
|
+
(event, file) => {
|
|
111
|
+
console.log("'%s' changed \n re-starting now", file);
|
|
112
|
+
closeWatchers();
|
|
113
|
+
spawnSync("npm", ["run", "tsc"], {
|
|
114
|
+
stdio: "inherit",
|
|
115
|
+
cwd: projectRoot,
|
|
116
|
+
});
|
|
117
|
+
process.exit();
|
|
118
|
+
}
|
|
119
|
+
)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
// watch plugin dirs
|
|
123
|
+
for (const pluginDir of pluginDirs) {
|
|
124
|
+
activeWatchers.push(
|
|
125
|
+
watch(
|
|
126
|
+
pluginDir,
|
|
127
|
+
watchCfg,
|
|
128
|
+
// event is either 'update' or 'remove'
|
|
129
|
+
(event, file) => {
|
|
130
|
+
console.log("'%s' changed \n re-starting now", file);
|
|
131
|
+
closeWatchers();
|
|
132
|
+
process.exit();
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
module.exports = {
|
|
140
|
+
listenForChanges,
|
|
141
|
+
getProjectRoot,
|
|
142
|
+
getPackagesDirectory,
|
|
143
|
+
getRelevantPackages,
|
|
144
|
+
getPluginDirectories,
|
|
145
|
+
closeWatchers,
|
|
146
|
+
};
|
package/routes/fields.js
CHANGED
|
@@ -38,11 +38,11 @@ const router = new Router();
|
|
|
38
38
|
module.exports = router;
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* @param {object} req
|
|
42
|
-
* @param {*} fkey_opts
|
|
43
|
-
* @param {*} existing_names
|
|
44
|
-
* @param {*} id
|
|
45
|
-
* @param {*} hasData
|
|
41
|
+
* @param {object} req
|
|
42
|
+
* @param {*} fkey_opts
|
|
43
|
+
* @param {*} existing_names
|
|
44
|
+
* @param {*} id
|
|
45
|
+
* @param {*} hasData
|
|
46
46
|
* @returns {Promise<Form>}
|
|
47
47
|
*/
|
|
48
48
|
const fieldForm = async (req, fkey_opts, existing_names, id, hasData) => {
|
|
@@ -137,7 +137,7 @@ const fieldForm = async (req, fkey_opts, existing_names, id, hasData) => {
|
|
|
137
137
|
};
|
|
138
138
|
|
|
139
139
|
/**
|
|
140
|
-
* @param {string} ctxType
|
|
140
|
+
* @param {string} ctxType
|
|
141
141
|
* @returns {object}
|
|
142
142
|
*/
|
|
143
143
|
const calcFieldType = (ctxType) =>
|
|
@@ -146,8 +146,8 @@ const calcFieldType = (ctxType) =>
|
|
|
146
146
|
: { type: ctxType };
|
|
147
147
|
|
|
148
148
|
/**
|
|
149
|
-
* @param {*} attrs
|
|
150
|
-
* @param {object} req
|
|
149
|
+
* @param {*} attrs
|
|
150
|
+
* @param {object} req
|
|
151
151
|
* @returns {*}
|
|
152
152
|
*/
|
|
153
153
|
const translateAttributes = (attrs, req) =>
|
|
@@ -156,8 +156,8 @@ const translateAttributes = (attrs, req) =>
|
|
|
156
156
|
: attrs;
|
|
157
157
|
|
|
158
158
|
/**
|
|
159
|
-
* @param {*} attr
|
|
160
|
-
* @param {*} req
|
|
159
|
+
* @param {*} attr
|
|
160
|
+
* @param {*} req
|
|
161
161
|
* @returns {object}
|
|
162
162
|
*/
|
|
163
163
|
const translateAttribute = (attr, req) => {
|
|
@@ -167,7 +167,7 @@ const translateAttribute = (attr, req) => {
|
|
|
167
167
|
};
|
|
168
168
|
|
|
169
169
|
/**
|
|
170
|
-
* @param {*} req
|
|
170
|
+
* @param {*} req
|
|
171
171
|
* @returns {Workflow}
|
|
172
172
|
*/
|
|
173
173
|
const fieldFlow = (req) =>
|
|
@@ -697,12 +697,12 @@ router.post(
|
|
|
697
697
|
if (!fv && field.type === "Key" && fieldview === "select")
|
|
698
698
|
res.send("<select disabled></select>");
|
|
699
699
|
else if (!fv) res.send("");
|
|
700
|
-
else if (fv.isEdit)
|
|
700
|
+
else if (fv.isEdit || fv.isFilter)
|
|
701
701
|
res.send(
|
|
702
702
|
fv.run(
|
|
703
703
|
field.name,
|
|
704
704
|
undefined,
|
|
705
|
-
{ disabled: true, ...configuration },
|
|
705
|
+
{ disabled: true, ...configuration, ...(field.attributes || {}) },
|
|
706
706
|
"",
|
|
707
707
|
false,
|
|
708
708
|
field
|
package/routes/index.js
CHANGED
|
@@ -4,6 +4,43 @@
|
|
|
4
4
|
* @module routes/index
|
|
5
5
|
* @subcategory routes
|
|
6
6
|
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* All files in the routes module.
|
|
10
|
+
* @namespace routes_overview
|
|
11
|
+
* @property {module:routes/actions} actions
|
|
12
|
+
* @property {module:routes/admin} admin
|
|
13
|
+
* @property {module:routes/api} api
|
|
14
|
+
* @property {module:routes/config} config
|
|
15
|
+
* @property {module:routes/crashlog} crashlog
|
|
16
|
+
* @property {module:routes/delete} delete
|
|
17
|
+
* @property {module:routes/edit} edit
|
|
18
|
+
* @property {module:routes/eventlog} eventlog
|
|
19
|
+
* @property {module:routes/events} events
|
|
20
|
+
* @property {module:routes/fields} fields
|
|
21
|
+
* @property {module:routes/files} files
|
|
22
|
+
* @property {module:routes/homepage} homepage
|
|
23
|
+
* @property {module:routes/infoarch} infoarch
|
|
24
|
+
* @property {module:routes/library} library
|
|
25
|
+
* @property {module:routes/list} list
|
|
26
|
+
* @property {module:routes/menu} menu
|
|
27
|
+
* @property {module:routes/packs} packs
|
|
28
|
+
* @property {module:routes/page} page
|
|
29
|
+
* @property {module:routes/pageedit} pageedit
|
|
30
|
+
* @property {module:routes/plugins} plugins
|
|
31
|
+
* @property {module:routes/scapi} scapi
|
|
32
|
+
* @property {module:routes/search} search
|
|
33
|
+
* @property {module:routes/settings} settings
|
|
34
|
+
* @property {module:routes/tables} tables
|
|
35
|
+
* @property {module:routes/tenant} tenant
|
|
36
|
+
* @property {module:routes/utils} utils
|
|
37
|
+
* @property {module:routes/view} view
|
|
38
|
+
* @property {module:routes/viewedit} viewedit
|
|
39
|
+
*
|
|
40
|
+
* @category server
|
|
41
|
+
* @subcategory routes
|
|
42
|
+
*/
|
|
43
|
+
|
|
7
44
|
const table = require("./tables");
|
|
8
45
|
const field = require("./fields");
|
|
9
46
|
const list = require("./list");
|
package/routes/view.js
CHANGED
|
@@ -68,7 +68,7 @@ router.get(
|
|
|
68
68
|
what: req.__("View"),
|
|
69
69
|
url: `/viewedit/edit/${encodeURIComponent(view.name)}`,
|
|
70
70
|
contents,
|
|
71
|
-
req
|
|
71
|
+
req,
|
|
72
72
|
})
|
|
73
73
|
);
|
|
74
74
|
})
|
|
@@ -92,18 +92,18 @@ router.post(
|
|
|
92
92
|
res.send("");
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
|
-
let query = {};
|
|
95
|
+
let query = req.body || {};
|
|
96
96
|
let row;
|
|
97
97
|
let table;
|
|
98
98
|
const sfs = await view.get_state_fields();
|
|
99
99
|
for (const sf of sfs) {
|
|
100
|
-
if (sf.required) {
|
|
100
|
+
if (sf.required && !query[sf.name]) {
|
|
101
101
|
if (!row) {
|
|
102
102
|
if (!table)
|
|
103
103
|
table = await Table.findOne(view.table_id || view.exttable_name);
|
|
104
104
|
row = await table.getRow({});
|
|
105
105
|
}
|
|
106
|
-
if(row) query[sf.name] = row[sf.name];
|
|
106
|
+
if (row) query[sf.name] = row[sf.name];
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
const contents = await view.run(query, { req, res });
|
package/serve.js
CHANGED
|
@@ -33,11 +33,14 @@ const { setTenant, getSessionStore } = require("./routes/utils");
|
|
|
33
33
|
const passport = require("passport");
|
|
34
34
|
const { authenticate } = require("passport");
|
|
35
35
|
const View = require("@saltcorn/data/models/view");
|
|
36
|
+
const {
|
|
37
|
+
listenForChanges,
|
|
38
|
+
getRelevantPackages,
|
|
39
|
+
getPluginDirectories,
|
|
40
|
+
} = require("./restart_watcher");
|
|
36
41
|
|
|
37
42
|
// helpful https://gist.github.com/jpoehls/2232358
|
|
38
|
-
|
|
39
43
|
/**
|
|
40
|
-
* @param {object} opts
|
|
41
44
|
* @param {object} opts
|
|
42
45
|
* @param {boolean} opts.disableMigrate
|
|
43
46
|
* @param {boolean} [useClusterAdaptor = true]
|
|
@@ -146,6 +149,7 @@ module.exports =
|
|
|
146
149
|
* @param {boolean} opts.watchReaper
|
|
147
150
|
* @param {boolean} opts.disableScheduler
|
|
148
151
|
* @param {number} opts.defaultNCPUs
|
|
152
|
+
* @param {boolean} opts.dev
|
|
149
153
|
* @param {...*} opts.appargs
|
|
150
154
|
* @returns {Promise<void>}
|
|
151
155
|
*/
|
|
@@ -154,8 +158,12 @@ module.exports =
|
|
|
154
158
|
watchReaper,
|
|
155
159
|
disableScheduler,
|
|
156
160
|
defaultNCPUs,
|
|
161
|
+
dev,
|
|
157
162
|
...appargs
|
|
158
163
|
} = {}) => {
|
|
164
|
+
if (dev && cluster.isMaster) {
|
|
165
|
+
listenForChanges(getRelevantPackages(), await getPluginDirectories());
|
|
166
|
+
}
|
|
159
167
|
const useNCpus = process.env.SALTCORN_NWORKERS
|
|
160
168
|
? +process.env.SALTCORN_NWORKERS
|
|
161
169
|
: defaultNCPUs;
|