noxt-server 0.1.14 → 0.1.16
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/README.md +3 -116
- package/noxt-server.js +37 -13
- package/package.json +8 -10
- package/units/bundler.js +56 -0
- package/units/bust-cache.js +30 -0
- package/units/compression.js +30 -0
- package/units/config.js +2 -2
- package/units/env.js +3 -2
- package/units/express.js +87 -54
- package/units/fetch-cache-fs.js +172 -45
- package/units/fetch-cache.js +1 -1
- package/units/fetch.js +31 -15
- package/units/hooks.js +22 -9
- package/units/image-resizer.js +263 -0
- package/units/logger.js +59 -8
- package/units/noxt-dev.js +4 -2
- package/units/noxt-plugin.js +98 -98
- package/units/noxt-router.js +25 -8
- package/units/noxt.js +3 -1
- package/units/plugin.js +1 -1
- package/units/reload.js +101 -12
- package/units/services.js +16 -12
- package/units/static.js +43 -15
- package/units/utils.js +18 -1
- package/units.txt +86 -119
- package/units/noxt-router-dev.js +0 -33
package/units/noxt-plugin.js
CHANGED
|
@@ -1,125 +1,125 @@
|
|
|
1
1
|
export const info = {
|
|
2
2
|
name: 'noxt-plugin',
|
|
3
3
|
description: 'Noxt Plugin',
|
|
4
|
-
requires: ['express'
|
|
4
|
+
requires: ['express'],
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
const pageContextHooks = {};
|
|
8
|
-
const serverContextHooks = {};
|
|
9
|
-
const componentExportsHooks = {};
|
|
10
|
-
const registerPageHooks = {};
|
|
11
|
-
const registerComponentHooks = {};
|
|
12
7
|
|
|
13
8
|
export default mlm => {
|
|
9
|
+
const requestApi = {};
|
|
10
|
+
const componentErrorHooks = {};
|
|
11
|
+
const requestContextHooks = {};
|
|
12
|
+
const serverContextHooks = {};
|
|
13
|
+
const componentExportsHooks = [];
|
|
14
|
+
const registerPageHooks = {};
|
|
15
|
+
const registerComponentHooks = {};
|
|
16
|
+
const componentChangedHooks = {}
|
|
14
17
|
|
|
15
|
-
const collector = (coll, desc) => (conf, unit) => {
|
|
16
|
-
for (const key in conf) {
|
|
17
|
-
const fn = conf[key];
|
|
18
|
-
mlm.assert.is.function(fn, desc);
|
|
19
|
-
mlm.assert.not(key in coll, 'Duplicate ' + desc + ' ' + key);
|
|
20
|
-
coll[key] = ({ fn, unit: unit.name });
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const runner = (
|
|
25
|
-
coll, each = (_, fn, ...args) => fn(...args)
|
|
26
|
-
) => async (...args) => {
|
|
27
|
-
for (const key in coll) {
|
|
28
|
-
const { fn } = coll[key];
|
|
29
|
-
await each(key, fn, ...args);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const arrayCollector = (coll, desc) => (conf, unit) => {
|
|
34
|
-
for (const key in conf) {
|
|
35
|
-
const fn = conf[key];
|
|
36
|
-
mlm.assert.is.function(fn, desc);
|
|
37
|
-
coll[key] ??= [];
|
|
38
|
-
coll[key].push({ fn, unit: unit.name });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const arrayRunner = (
|
|
43
|
-
coll, each = (_, fn, ...args) => fn(...args)
|
|
44
|
-
) => async (...args) => {
|
|
45
|
-
for (const key in coll) {
|
|
46
|
-
const handlers = coll[key];
|
|
47
|
-
for (const handler of handlers) {
|
|
48
|
-
await each(key, handler.fn, ...args);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
18
|
const globalServerContext = {};
|
|
53
19
|
return ({
|
|
54
|
-
'
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
'
|
|
60
|
-
|
|
61
|
-
|
|
20
|
+
'collect.requestContext': {
|
|
21
|
+
target: requestContextHooks,
|
|
22
|
+
is: 'function',
|
|
23
|
+
mode: 'object'
|
|
24
|
+
},
|
|
25
|
+
'collect.api': {
|
|
26
|
+
target: requestApi,
|
|
27
|
+
is: 'function',
|
|
28
|
+
mode: 'object',
|
|
29
|
+
},
|
|
30
|
+
'requestContext.api': ({ ctx }) => new Proxy({}, {
|
|
31
|
+
ownKeys: () => Object.keys(requestApi),
|
|
32
|
+
get: (target, key) => (target[key] ??= requestApi[key]?.({ctx}))
|
|
33
|
+
}),
|
|
34
|
+
'collect.componentExports': {
|
|
35
|
+
target: componentExportsHooks,
|
|
36
|
+
is: 'object',
|
|
37
|
+
mode: 'array'
|
|
38
|
+
},
|
|
39
|
+
'collect.serverContext': {
|
|
40
|
+
target: serverContextHooks,
|
|
41
|
+
is: 'function',
|
|
42
|
+
mode: 'object'
|
|
43
|
+
},
|
|
44
|
+
'collect.registerPage': {
|
|
45
|
+
target: registerPageHooks,
|
|
46
|
+
is: 'function',
|
|
47
|
+
mode: 'object',
|
|
62
48
|
},
|
|
49
|
+
'collect.registerComponent': {
|
|
50
|
+
target: registerComponentHooks,
|
|
51
|
+
is: 'function',
|
|
52
|
+
mode: 'object',
|
|
53
|
+
},
|
|
54
|
+
'collect.componentChanged': {
|
|
55
|
+
target: componentChangedHooks,
|
|
56
|
+
is: 'function',
|
|
57
|
+
mode: 'object',
|
|
58
|
+
},
|
|
59
|
+
'collect.componentError': {
|
|
60
|
+
target: componentErrorHooks,
|
|
61
|
+
is: 'function',
|
|
62
|
+
mode: 'object',
|
|
63
|
+
},
|
|
64
|
+
'serverContext.services': () => mlm.services,
|
|
63
65
|
'serverContext.utils': () => mlm.utils,
|
|
64
66
|
'serverContext.DEV': () => mlm.DEV,
|
|
65
67
|
'serverContext.PROD': () => mlm.PROD,
|
|
66
68
|
onStart: async () => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
const ctx = globalServerContext;
|
|
70
|
+
for (const key in serverContextHooks) {
|
|
71
|
+
ctx[key] = await serverContextHooks[key]({ ctx });
|
|
72
|
+
}
|
|
69
73
|
},
|
|
70
|
-
'services.noxt': () => new class
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
'services.noxt': () => new class NoxtPluginService {
|
|
75
|
+
get context() {
|
|
76
|
+
return globalServerContext;
|
|
77
|
+
}
|
|
78
|
+
get hooks() {
|
|
79
|
+
return {
|
|
80
|
+
beforeRequest: async ({ ctx }) => {
|
|
81
|
+
Object.assign(ctx, this.context);
|
|
82
|
+
for (const key in requestContextHooks) {
|
|
83
|
+
ctx[key] = await requestContextHooks[key]({ ctx });
|
|
84
|
+
}
|
|
79
85
|
},
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
86
|
+
beforeRender: async ({ ...args }) => {
|
|
87
|
+
for (const item of componentExportsHooks) {
|
|
88
|
+
for (const key in item) {
|
|
89
|
+
if (!(key in args.module)) continue;
|
|
90
|
+
await item[key]({ exported: args.module[key], ...args });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
registerPage: async ({ module, component }) => {
|
|
95
|
+
for (const fn of Object.values(registerPageHooks)) {
|
|
96
|
+
await fn({ module, component });
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
registerComponent: async (...args) => {
|
|
100
|
+
for (const fn of Object.values(registerComponentHooks)) {
|
|
101
|
+
await fn(...args);
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
componentChanged: async ({ module, component }) => {
|
|
105
|
+
for (const fn of Object.values(componentChangedHooks)) {
|
|
106
|
+
await fn({ module, component });
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
componentError: async ({ name, error }) => {
|
|
110
|
+
for (const fn of Object.values(componentErrorHooks)) {
|
|
111
|
+
await fn({ name, error });
|
|
83
112
|
}
|
|
84
|
-
),
|
|
85
|
-
],
|
|
86
|
-
beforeRender: arrayRunner(componentExportsHooks,
|
|
87
|
-
async (key, fn, { module, props, ctx }) => {
|
|
88
|
-
//mlm.log('beforeRender', unit, key, Object.keys(props));
|
|
89
|
-
if (!(key in module)) return;
|
|
90
|
-
const exported = module[key];
|
|
91
|
-
await fn({ exported, props, ctx, module })
|
|
92
|
-
//mlm.log('beforeRender', key, Object.keys(props));
|
|
93
|
-
}
|
|
94
|
-
),
|
|
95
|
-
registerPage: runner(registerPageHooks,
|
|
96
|
-
async (key, fn, { module, component }) => {
|
|
97
|
-
await fn({ module, component })
|
|
98
|
-
}
|
|
99
|
-
),
|
|
100
|
-
registerComponent: runner(registerComponentHooks,
|
|
101
|
-
async (key, fn, { module, component }) => {
|
|
102
|
-
await fn({ module, component })
|
|
103
113
|
}
|
|
104
|
-
)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
report() {
|
|
108
|
-
return {
|
|
109
|
-
pageContext: pageContextHooks,
|
|
110
|
-
serverContext: serverContextHooks,
|
|
111
|
-
componentExports: componentExportsHooks,
|
|
112
|
-
registerPage: registerPageHooks,
|
|
113
|
-
registerComponent: registerComponentHooks
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
},
|
|
117
117
|
'registerPage.Link'({ component, module }) {
|
|
118
118
|
const As = module.Link ?? 'a';
|
|
119
|
-
component.Link = ({ text, children,
|
|
120
|
-
const href = component.getRoutePath(
|
|
121
|
-
return { type: As, props: { ...attrs, href, children: text ?? children }
|
|
119
|
+
component.Link = ({ text, children, params={}, ...attrs }, ctx) => {
|
|
120
|
+
const href = component.getRoutePath(params, ctx);
|
|
121
|
+
return { type: As, props: { ...attrs, href, children: text ?? children } };
|
|
122
122
|
}
|
|
123
|
-
}
|
|
123
|
+
},
|
|
124
124
|
})
|
|
125
125
|
}
|
package/units/noxt-router.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export const info = {
|
|
2
2
|
name: 'noxt-router',
|
|
3
3
|
description: 'Sets up a Noxt Router',
|
|
4
|
-
requires: ['plugin'],
|
|
4
|
+
requires: ['noxt-plugin'],
|
|
5
5
|
provides: ['#noxt-router'],
|
|
6
|
-
|
|
7
|
-
'noxt-js-middleware'
|
|
8
|
-
}
|
|
6
|
+
packages: {
|
|
7
|
+
noxt: 'noxt-js-middleware'
|
|
8
|
+
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export default mlm => ({
|
|
@@ -14,13 +14,30 @@ export default mlm => ({
|
|
|
14
14
|
is: ['string'],
|
|
15
15
|
default: ['views']
|
|
16
16
|
},
|
|
17
|
-
'middleware.noxt': async (app) => {
|
|
18
|
-
const { default: noxt } =
|
|
17
|
+
'prod.middleware.noxt': async (app) => {
|
|
18
|
+
const { default: noxt } = mlm.packages.noxt;
|
|
19
|
+
const noxtRouter = await noxt({
|
|
20
|
+
context: mlm.services.noxt.context,
|
|
21
|
+
views: mlm.config.views,
|
|
22
|
+
hooks: mlm.services.noxt.hooks,
|
|
23
|
+
})
|
|
24
|
+
return noxtRouter
|
|
25
|
+
},
|
|
26
|
+
'dev.middleware.noxt': async (app) => {
|
|
27
|
+
const { default: noxt } = mlm.packages.noxt;
|
|
19
28
|
const noxtRouter = await noxt({
|
|
20
|
-
context: mlm.
|
|
29
|
+
context: mlm.services.noxt.context,
|
|
21
30
|
views: mlm.config.views,
|
|
22
|
-
hooks: mlm.services.noxt.
|
|
31
|
+
hooks: mlm.services.noxt.hooks,
|
|
32
|
+
watch: true
|
|
23
33
|
})
|
|
24
34
|
return noxtRouter
|
|
25
35
|
},
|
|
36
|
+
'dev.componentChanged.reload': ({ name, component }) => {
|
|
37
|
+
mlm.services.reload.refresh();
|
|
38
|
+
},
|
|
39
|
+
'dev.componentError.reload': async ({ name, error }) => {
|
|
40
|
+
mlm.services.reload.error(error);
|
|
41
|
+
},
|
|
42
|
+
'dev.requestContext.reload': ({ ctx }) => ctx.slot('script', 'noxt-reload', '/_reload.js'),
|
|
26
43
|
})
|
package/units/noxt.js
CHANGED
package/units/plugin.js
CHANGED
package/units/reload.js
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
export const info = {
|
|
2
2
|
name: 'reload',
|
|
3
3
|
description: 'Hot reload middleware',
|
|
4
|
-
requires: ['
|
|
5
|
-
|
|
6
|
-
'express': '^5.0.0',
|
|
7
|
-
},
|
|
4
|
+
requires: ['express'],
|
|
5
|
+
provides: ['#reload'],
|
|
8
6
|
}
|
|
9
7
|
|
|
10
8
|
const clients = new Set();
|
|
11
9
|
export default mlm => ({
|
|
12
|
-
'
|
|
10
|
+
'services.reload': () => ({
|
|
11
|
+
refresh: forceReload,
|
|
12
|
+
error: sendError
|
|
13
|
+
}),
|
|
14
|
+
'define.refresh': () => forceReload,
|
|
15
|
+
'define.error': () => sendError,
|
|
13
16
|
'middleware.reload': async () => {
|
|
14
|
-
const
|
|
15
|
-
const router = express.Router();
|
|
17
|
+
const router = mlm.services.express.Router();
|
|
16
18
|
router.get('/_reload.js', (req, res) => {
|
|
19
|
+
res.logGroup = 'reload';
|
|
17
20
|
res.set('Content-Type', 'text/javascript');
|
|
18
21
|
res.send(reloadJs);
|
|
19
22
|
});
|
|
20
23
|
|
|
21
24
|
router.get('/_events', (req, res) => {
|
|
25
|
+
res.logGroup = 'reload';
|
|
22
26
|
res.writeHead(200, {
|
|
23
27
|
'Content-Type': 'text/event-stream',
|
|
24
28
|
'Cache-Control': 'no-cache',
|
|
@@ -34,10 +38,9 @@ export default mlm => ({
|
|
|
34
38
|
req.on('error', () => clients.delete(res));
|
|
35
39
|
res.on('error', () => clients.delete(res));
|
|
36
40
|
});
|
|
37
|
-
|
|
38
41
|
return router
|
|
39
42
|
},
|
|
40
|
-
|
|
43
|
+
onStart() {
|
|
41
44
|
process.on('SIGUSR2', handleSignal)
|
|
42
45
|
},
|
|
43
46
|
onStop() {
|
|
@@ -45,6 +48,27 @@ export default mlm => ({
|
|
|
45
48
|
}
|
|
46
49
|
})
|
|
47
50
|
|
|
51
|
+
async function forceReload() {
|
|
52
|
+
const promises = Array.from(clients).map(async client => {
|
|
53
|
+
client.write('event: refresh\ndata:\n\n');
|
|
54
|
+
return new Promise(resolve => client.end(resolve));
|
|
55
|
+
});
|
|
56
|
+
await Promise.all(promises);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function sendError(error) {
|
|
60
|
+
const errorData = {
|
|
61
|
+
message: error.message,
|
|
62
|
+
stack: error.stack,
|
|
63
|
+
name: error.name
|
|
64
|
+
};
|
|
65
|
+
const data = JSON.stringify(errorData).replace(/\n/g, '\\n');
|
|
66
|
+
|
|
67
|
+
clients.forEach(client => {
|
|
68
|
+
client.write(`event: error\ndata: ${data}\n\n`);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
48
72
|
async function handleSignal() {
|
|
49
73
|
const promises = Array.from(clients).map(async client => {
|
|
50
74
|
client.write('event: reload\ndata:\n\n');
|
|
@@ -52,11 +76,13 @@ async function handleSignal() {
|
|
|
52
76
|
});
|
|
53
77
|
await Promise.all(promises);
|
|
54
78
|
process.exit(0);
|
|
55
|
-
}
|
|
79
|
+
}
|
|
56
80
|
|
|
57
81
|
const reloadJs = `
|
|
58
|
-
|
|
82
|
+
const eventSource = new EventSource('/_events');
|
|
59
83
|
let reload = false;
|
|
84
|
+
let errorOverlay = null;
|
|
85
|
+
|
|
60
86
|
eventSource.addEventListener('connected', () => {
|
|
61
87
|
if (reload) {
|
|
62
88
|
console.log('%c NOXT ','color: #ffd; background-color: #080', 'Reloading...' );
|
|
@@ -64,13 +90,76 @@ eventSource.addEventListener('connected', () => {
|
|
|
64
90
|
} else {
|
|
65
91
|
console.log('%c NOXT ', 'color: #ffd; background-color: #080', 'Connected.' );
|
|
66
92
|
}
|
|
67
|
-
|
|
93
|
+
hideError();
|
|
68
94
|
});
|
|
95
|
+
|
|
69
96
|
eventSource.addEventListener('reload', () => {
|
|
70
97
|
console.log('%c NOXT ','color: #ffd; background-color: #080', 'Restarting...' );
|
|
71
98
|
reload = true;
|
|
72
99
|
});
|
|
100
|
+
|
|
101
|
+
eventSource.addEventListener('refresh', () => {
|
|
102
|
+
console.log('%c NOXT ','color: #ffd; background-color: #080', 'Refresh...' );
|
|
103
|
+
window.location.reload();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
eventSource.addEventListener('error', (e) => {
|
|
107
|
+
const error = JSON.parse(e.data);
|
|
108
|
+
console.error('%c NOXT ','color: #ffd; background-color: #f00', 'Error:', error.message);
|
|
109
|
+
showError(error);
|
|
110
|
+
});
|
|
111
|
+
|
|
73
112
|
window.addEventListener('beforeunload', () => {
|
|
74
113
|
eventSource.close();
|
|
75
114
|
});
|
|
115
|
+
|
|
116
|
+
function showError(error) {
|
|
117
|
+
hideError();
|
|
118
|
+
|
|
119
|
+
errorOverlay = document.createElement('dialog');
|
|
120
|
+
errorOverlay.style.cssText = \`
|
|
121
|
+
position: fixed;
|
|
122
|
+
top: 0;
|
|
123
|
+
max-width: 100vw;
|
|
124
|
+
max-height: 100vh;
|
|
125
|
+
width: 100%;
|
|
126
|
+
height: 100%;
|
|
127
|
+
margin: 0;
|
|
128
|
+
padding: 20px;
|
|
129
|
+
background: rgba(0, 0, 0, 0.95);
|
|
130
|
+
color: #fff;
|
|
131
|
+
border: none;
|
|
132
|
+
font-family: monospace;
|
|
133
|
+
overflow: auto;
|
|
134
|
+
\`;
|
|
135
|
+
|
|
136
|
+
errorOverlay.innerHTML = \`
|
|
137
|
+
<h1 style="color: #f00; margin: 0 0 1em 0;">\${error.name || 'Error'}</h1>
|
|
138
|
+
<p style="font-size: 16px; margin-bottom: 1em;">\${error.message}</p>
|
|
139
|
+
<pre style="font-size: 14px; white-space: pre-wrap; overflow-x: auto;">\${error.stack || ''}</pre>
|
|
140
|
+
\`;
|
|
141
|
+
|
|
142
|
+
document.body.appendChild(errorOverlay);
|
|
143
|
+
errorOverlay.showModal();
|
|
144
|
+
|
|
145
|
+
errorOverlay.addEventListener('click', (e) => {
|
|
146
|
+
if (e.target === errorOverlay) hideError();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const closeHandler = (e) => {
|
|
150
|
+
if (e.key === 'Escape') {
|
|
151
|
+
hideError();
|
|
152
|
+
document.removeEventListener('keydown', closeHandler);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
document.addEventListener('keydown', closeHandler);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function hideError() {
|
|
159
|
+
if (errorOverlay) {
|
|
160
|
+
errorOverlay.close();
|
|
161
|
+
errorOverlay.remove();
|
|
162
|
+
errorOverlay = null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
76
165
|
`
|
package/units/services.js
CHANGED
|
@@ -5,17 +5,21 @@ export const info = {
|
|
|
5
5
|
requires: ['utils']
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
const services = {}
|
|
9
8
|
|
|
10
|
-
export default mlm =>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
export default mlm => {
|
|
10
|
+
const services = {}
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
'define.services': () => mlm.utils.readOnly(services, 'services'),
|
|
14
|
+
'collect.services': {
|
|
15
|
+
target: services,
|
|
16
|
+
is: 'function',
|
|
17
|
+
mode: 'object',
|
|
18
|
+
map: (fn, key) => {
|
|
19
|
+
const service = fn(mlm)
|
|
20
|
+
mlm.assert.is.object(service, 'service');
|
|
21
|
+
return service
|
|
22
|
+
}
|
|
19
23
|
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
24
|
+
}
|
|
25
|
+
}
|
package/units/static.js
CHANGED
|
@@ -2,20 +2,48 @@ export const info = {
|
|
|
2
2
|
name: 'static',
|
|
3
3
|
description: 'Static middleware',
|
|
4
4
|
requires: ['express'],
|
|
5
|
-
|
|
6
|
-
'serve-static': '^1.15.0'
|
|
7
|
-
},
|
|
5
|
+
packages: ['express']
|
|
8
6
|
}
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
8
|
+
import { resolve } from 'path';
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
|
|
11
|
+
export default mlm => {
|
|
12
|
+
let watcher;
|
|
13
|
+
return {
|
|
14
|
+
'config.static': {
|
|
15
|
+
is: 'string',
|
|
16
|
+
default: 'public',
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
'prod.middleware.static': async () => {
|
|
20
|
+
const dir = mlm.config.static;
|
|
21
|
+
if (!dir) return null;
|
|
22
|
+
return mlm.packages.express.static(resolve(dir), {
|
|
23
|
+
setHeaders: res => res.logGroup = 'static',
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
'dev.middleware.static': async () => {
|
|
27
|
+
const dir = mlm.config.static;
|
|
28
|
+
if (!dir) return null;
|
|
29
|
+
return mlm.packages.express.static(resolve(dir), {
|
|
30
|
+
etag: false,
|
|
31
|
+
cacheControl: false,
|
|
32
|
+
setHeaders: res => res.logGroup = 'static',
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
'dev.onStart'() {
|
|
36
|
+
const dir = mlm.config.static;
|
|
37
|
+
if (!dir) return;
|
|
38
|
+
watcher = fs.watch(dir, { recursive: true }, mlm.utils.debounce(() => {
|
|
39
|
+
mlm.services.reload.refresh()
|
|
40
|
+
}, 50))
|
|
41
|
+
},
|
|
42
|
+
'dev.onStop'() {
|
|
43
|
+
if (watcher) {
|
|
44
|
+
watcher.close();
|
|
45
|
+
watcher = null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
package/units/utils.js
CHANGED
|
@@ -7,6 +7,13 @@ export const info = {
|
|
|
7
7
|
export default mlm => {
|
|
8
8
|
|
|
9
9
|
const utils = {};
|
|
10
|
+
utils.debounce = (fn, delay) => {
|
|
11
|
+
let timeout;
|
|
12
|
+
return (...args) => {
|
|
13
|
+
clearTimeout(timeout);
|
|
14
|
+
timeout = setTimeout(() => fn(...args), delay);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
10
17
|
utils.eval = (fn, ...args) => typeof fn === 'function' ? fn(...args) : fn;
|
|
11
18
|
utils.readOnly = (obj, { label = 'object' } = {}) => new Proxy(obj, {
|
|
12
19
|
get: (t, k) => t[k],
|
|
@@ -20,7 +27,7 @@ export default mlm => {
|
|
|
20
27
|
} = {}) => {
|
|
21
28
|
const modes = {
|
|
22
29
|
array: () => source => {
|
|
23
|
-
for (let value of source) {
|
|
30
|
+
for (let value of [].concat(source)) {
|
|
24
31
|
if (filter && !filter(value)) continue;
|
|
25
32
|
if (is) mlm.assert.is(is, value, label);
|
|
26
33
|
if (map) value = map(value);
|
|
@@ -71,8 +78,18 @@ export default mlm => {
|
|
|
71
78
|
mlm.assert(mode in modes, 'Unknown mode ' + mode);
|
|
72
79
|
return modes[mode]();
|
|
73
80
|
}
|
|
81
|
+
|
|
74
82
|
return ({
|
|
75
83
|
'define.utils': () => utils.readOnly(utils, 'utils'),
|
|
76
84
|
'register.utils': utils.collector(utils, { is: 'function', mode: 'object', map: (fn, key) => { mlm.log('utils', key); return fn; } }),
|
|
85
|
+
'inject.collect': async (confs,unit) => {
|
|
86
|
+
const ret = {}
|
|
87
|
+
for (const key in confs) {
|
|
88
|
+
const { target, ...conf } = confs[key];
|
|
89
|
+
conf.label = key;
|
|
90
|
+
ret[key] = utils.collector(target, conf);
|
|
91
|
+
}
|
|
92
|
+
return {register:ret}
|
|
93
|
+
},
|
|
77
94
|
})
|
|
78
95
|
}
|