@webqit/webflo 0.11.60 → 0.11.61
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/.gitignore +7 -7
- package/LICENSE +20 -20
- package/README.md +2079 -2074
- package/docker/Dockerfile +42 -42
- package/docker/README.md +91 -91
- package/docker/package.json +2 -2
- package/package.json +80 -81
- package/src/Context.js +79 -79
- package/src/config-pi/deployment/Env.js +68 -68
- package/src/config-pi/deployment/Layout.js +63 -63
- package/src/config-pi/deployment/Origins.js +139 -139
- package/src/config-pi/deployment/Proxy.js +74 -74
- package/src/config-pi/deployment/index.js +17 -17
- package/src/config-pi/index.js +15 -15
- package/src/config-pi/runtime/Client.js +116 -98
- package/src/config-pi/runtime/Server.js +125 -125
- package/src/config-pi/runtime/client/Worker.js +109 -134
- package/src/config-pi/runtime/client/index.js +11 -11
- package/src/config-pi/runtime/index.js +17 -17
- package/src/config-pi/runtime/server/Headers.js +74 -74
- package/src/config-pi/runtime/server/Redirects.js +69 -69
- package/src/config-pi/runtime/server/index.js +13 -13
- package/src/config-pi/static/Manifest.js +319 -319
- package/src/config-pi/static/Ssg.js +49 -49
- package/src/config-pi/static/index.js +13 -13
- package/src/deployment-pi/index.js +10 -10
- package/src/deployment-pi/origins/index.js +216 -216
- package/src/index.js +19 -19
- package/src/runtime-pi/Application.js +28 -28
- package/src/runtime-pi/Cookies.js +81 -81
- package/src/runtime-pi/HttpEvent.js +106 -106
- package/src/runtime-pi/Router.js +130 -130
- package/src/runtime-pi/Runtime.js +20 -20
- package/src/runtime-pi/client/Application.js +76 -100
- package/src/runtime-pi/client/Context.js +7 -7
- package/src/runtime-pi/client/Router.js +48 -48
- package/src/runtime-pi/client/Runtime.js +524 -331
- package/src/runtime-pi/client/Url.js +204 -205
- package/src/runtime-pi/client/Workport.js +190 -178
- package/src/runtime-pi/client/createStorage.js +57 -56
- package/src/runtime-pi/client/generate.js +480 -471
- package/src/runtime-pi/client/index.js +21 -21
- package/src/runtime-pi/client/worker/Application.js +44 -44
- package/src/runtime-pi/client/worker/Context.js +7 -7
- package/src/runtime-pi/client/worker/Runtime.js +274 -268
- package/src/runtime-pi/client/worker/Workport.js +77 -89
- package/src/runtime-pi/client/worker/index.js +21 -21
- package/src/runtime-pi/index.js +13 -13
- package/src/runtime-pi/server/Application.js +100 -115
- package/src/runtime-pi/server/Context.js +15 -15
- package/src/runtime-pi/server/Router.js +159 -159
- package/src/runtime-pi/server/Runtime.js +557 -556
- package/src/runtime-pi/server/index.js +21 -21
- package/src/runtime-pi/util-http.js +85 -85
- package/src/runtime-pi/util-url.js +146 -146
- package/src/runtime-pi/xFormData.js +23 -23
- package/src/runtime-pi/xHeaders.js +145 -145
- package/src/runtime-pi/xRequest.js +45 -45
- package/src/runtime-pi/xRequestHeaders.js +108 -108
- package/src/runtime-pi/xResponse.js +32 -32
- package/src/runtime-pi/xResponseHeaders.js +116 -116
- package/src/runtime-pi/xURL.js +105 -105
- package/src/runtime-pi/xfetch.js +22 -22
- package/src/runtime-pi/xxHttpMessage.js +101 -101
- package/src/services-pi/cert/http-auth-hook.js +22 -22
- package/src/services-pi/cert/http-cleanup-hook.js +22 -22
- package/src/services-pi/cert/index.js +79 -79
- package/src/services-pi/index.js +8 -8
- package/src/static-pi/index.js +10 -10
- package/src/webflo.js +30 -30
- package/test/index.test.js +26 -26
- package/test/site/package.json +9 -9
- package/test/site/public/bundle.html +5 -5
- package/test/site/public/bundle.html.json +3 -3
- package/test/site/public/bundle.js +2 -2
- package/test/site/public/bundle.webflo.js +15 -15
- package/test/site/public/index.html +29 -29
- package/test/site/public/index1.html +34 -34
- package/test/site/public/page-2/bundle.html +4 -4
- package/test/site/public/page-2/bundle.js +2 -2
- package/test/site/public/page-2/index.html +45 -45
- package/test/site/public/page-2/main.html +2 -2
- package/test/site/public/page-4/subpage/bundle.js +2 -2
- package/test/site/public/page-4/subpage/index.html +30 -30
- package/test/site/public/sparoots.json +4 -4
- package/test/site/public/worker.js +3 -3
- package/test/site/server/index.js +15 -15
- package/src/runtime-pi/client/oohtml/full.js +0 -7
- package/src/runtime-pi/client/oohtml/namespacing.js +0 -7
- package/src/runtime-pi/client/oohtml/scripting.js +0 -8
- package/src/runtime-pi/client/oohtml/templating.js +0 -8
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import { _isTypeObject } from '@webqit/util/js/index.js';
|
|
6
|
-
import xFormData from './xFormData.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* The _Request Mixin
|
|
10
|
-
*/
|
|
11
|
-
const xxHttpMessage = (whatwagHttpMessage, xHeaders) => {
|
|
12
|
-
const HttpMessage = class extends whatwagHttpMessage {
|
|
13
|
-
|
|
14
|
-
constructor(input, init, meta) {
|
|
15
|
-
// ------------
|
|
16
|
-
if (init.headers) { init = { ...init, headers: new xHeaders(init.headers) }; }
|
|
17
|
-
super(input, init);
|
|
18
|
-
if (meta.headers) { this.headers.json(meta.headers); }
|
|
19
|
-
// ------------
|
|
20
|
-
let attrs = {};
|
|
21
|
-
Object.defineProperty(this, '_attrs', { get: () => attrs });
|
|
22
|
-
Object.defineProperty(this, 'meta', { get: () => meta });
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
get attrs() {
|
|
26
|
-
return this._attrs || {};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
clone() {
|
|
30
|
-
return new this.constructor(super.clone());
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
get headers() {
|
|
34
|
-
xHeaders.compat(super.headers);
|
|
35
|
-
return super.headers;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
get url() {
|
|
39
|
-
return 'url' in this.attrs ? this.attrs.url : super.url;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async arrayBuffer() {
|
|
43
|
-
if (this.meta.type === 'ArrayBuffer') { return this.meta.body; }
|
|
44
|
-
return super.arrayBuffer();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async blob() {
|
|
48
|
-
if (['Blob', 'File'].includes(this.meta.type)) { return this.meta.body; }
|
|
49
|
-
return super.blob();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async formData() {
|
|
53
|
-
let formData;
|
|
54
|
-
if (this.meta.type === 'FormData' && this.meta.body instanceof FormData) {
|
|
55
|
-
formData = this.meta.body;
|
|
56
|
-
} else { formData = await super.formData(); }
|
|
57
|
-
if (formData) { formData = xFormData.compat(formData); }
|
|
58
|
-
return formData;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async json() {
|
|
62
|
-
if (this.meta.type === 'json' && _isTypeObject(this.meta.body)) { return this.meta.body; }
|
|
63
|
-
return super.json();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async text() {
|
|
67
|
-
if (this.meta.type === 'json' && !_isTypeObject(this.meta.body)) { return this.meta.body; }
|
|
68
|
-
return super.text();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Resolve
|
|
72
|
-
jsonfy(force = false) {
|
|
73
|
-
if (!this.meta.jsonfied || force) {
|
|
74
|
-
this.meta.jsonfied = new Promise(async (resolve, reject) => {
|
|
75
|
-
let jsonfied;
|
|
76
|
-
let contentType = this.headers.get('Content-Type') || '';
|
|
77
|
-
try {
|
|
78
|
-
if (contentType === 'application/x-www-form-urlencoded' || contentType.startsWith('multipart/form-data')) {
|
|
79
|
-
const formData = await this.formData();
|
|
80
|
-
jsonfied = await formData?.json();
|
|
81
|
-
} else if (contentType === 'application/json') {
|
|
82
|
-
jsonfied = await this.json();
|
|
83
|
-
} else if (contentType === 'text/plain') {
|
|
84
|
-
jsonfied = await this.text();
|
|
85
|
-
}
|
|
86
|
-
resolve(jsonfied);
|
|
87
|
-
} catch(e) {
|
|
88
|
-
reject(e);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
return this.meta.jsonfied;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
};
|
|
96
|
-
// ----------
|
|
97
|
-
HttpMessage.Headers = xHeaders;
|
|
98
|
-
// ----------
|
|
99
|
-
return HttpMessage;
|
|
100
|
-
}
|
|
101
|
-
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import { _isTypeObject } from '@webqit/util/js/index.js';
|
|
6
|
+
import xFormData from './xFormData.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The _Request Mixin
|
|
10
|
+
*/
|
|
11
|
+
const xxHttpMessage = (whatwagHttpMessage, xHeaders) => {
|
|
12
|
+
const HttpMessage = class extends whatwagHttpMessage {
|
|
13
|
+
|
|
14
|
+
constructor(input, init, meta) {
|
|
15
|
+
// ------------
|
|
16
|
+
if (init.headers) { init = { ...init, headers: new xHeaders(init.headers) }; }
|
|
17
|
+
super(input, init);
|
|
18
|
+
if (meta.headers) { this.headers.json(meta.headers); }
|
|
19
|
+
// ------------
|
|
20
|
+
let attrs = {};
|
|
21
|
+
Object.defineProperty(this, '_attrs', { get: () => attrs });
|
|
22
|
+
Object.defineProperty(this, 'meta', { get: () => meta });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get attrs() {
|
|
26
|
+
return this._attrs || {};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
clone() {
|
|
30
|
+
return new this.constructor(super.clone());
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get headers() {
|
|
34
|
+
xHeaders.compat(super.headers);
|
|
35
|
+
return super.headers;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get url() {
|
|
39
|
+
return 'url' in this.attrs ? this.attrs.url : super.url;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async arrayBuffer() {
|
|
43
|
+
if (this.meta.type === 'ArrayBuffer') { return this.meta.body; }
|
|
44
|
+
return super.arrayBuffer();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async blob() {
|
|
48
|
+
if (['Blob', 'File'].includes(this.meta.type)) { return this.meta.body; }
|
|
49
|
+
return super.blob();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async formData() {
|
|
53
|
+
let formData;
|
|
54
|
+
if (this.meta.type === 'FormData' && this.meta.body instanceof FormData) {
|
|
55
|
+
formData = this.meta.body;
|
|
56
|
+
} else { formData = await super.formData(); }
|
|
57
|
+
if (formData) { formData = xFormData.compat(formData); }
|
|
58
|
+
return formData;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async json() {
|
|
62
|
+
if (this.meta.type === 'json' && _isTypeObject(this.meta.body)) { return this.meta.body; }
|
|
63
|
+
return super.json();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async text() {
|
|
67
|
+
if (this.meta.type === 'json' && !_isTypeObject(this.meta.body)) { return this.meta.body; }
|
|
68
|
+
return super.text();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Resolve
|
|
72
|
+
jsonfy(force = false) {
|
|
73
|
+
if (!this.meta.jsonfied || force) {
|
|
74
|
+
this.meta.jsonfied = new Promise(async (resolve, reject) => {
|
|
75
|
+
let jsonfied;
|
|
76
|
+
let contentType = this.headers.get('Content-Type') || '';
|
|
77
|
+
try {
|
|
78
|
+
if (contentType === 'application/x-www-form-urlencoded' || contentType.startsWith('multipart/form-data')) {
|
|
79
|
+
const formData = await this.formData();
|
|
80
|
+
jsonfied = await formData?.json();
|
|
81
|
+
} else if (contentType === 'application/json') {
|
|
82
|
+
jsonfied = await this.json();
|
|
83
|
+
} else if (contentType === 'text/plain') {
|
|
84
|
+
jsonfied = await this.text();
|
|
85
|
+
}
|
|
86
|
+
resolve(jsonfied);
|
|
87
|
+
} catch(e) {
|
|
88
|
+
reject(e);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return this.meta.jsonfied;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
};
|
|
96
|
+
// ----------
|
|
97
|
+
HttpMessage.Headers = xHeaders;
|
|
98
|
+
// ----------
|
|
99
|
+
return HttpMessage;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
102
|
export default xxHttpMessage;
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* imports
|
|
5
|
-
*/
|
|
6
|
-
import Fs from 'fs';
|
|
7
|
-
import Path from 'path';
|
|
8
|
-
import Layout from '../../config-pi/deployment/Layout.js';
|
|
9
|
-
|
|
10
|
-
// ------------------------------------------
|
|
11
|
-
|
|
12
|
-
const domain = process.env.CERTBOT_DOMAIN,
|
|
13
|
-
validation = process.env.CERTBOT_VALIDATION,
|
|
14
|
-
token = process.env.CERTBOT_TOKEN,
|
|
15
|
-
remainingChallenges = process.env.CERTBOT_REMAINING_CHALLENGES || 0/*,
|
|
16
|
-
allDomains = process.env.CERTBOT_ALL_DOMAINS.split(',')*/
|
|
17
|
-
;
|
|
18
|
-
(async function() {
|
|
19
|
-
const layout = await (new Layout({ name: 'webflo', flags: {} })).read();
|
|
20
|
-
const acmeDir = Path.join(layout.PUBLIC_DIR, './.well-known/acme-challenge/');
|
|
21
|
-
Fs.mkdirSync(acmeDir, {recursive:true});
|
|
22
|
-
Fs.writeFileSync(Path.join(acmeDir, token), validation);
|
|
23
|
-
})();
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* imports
|
|
5
|
+
*/
|
|
6
|
+
import Fs from 'fs';
|
|
7
|
+
import Path from 'path';
|
|
8
|
+
import Layout from '../../config-pi/deployment/Layout.js';
|
|
9
|
+
|
|
10
|
+
// ------------------------------------------
|
|
11
|
+
|
|
12
|
+
const domain = process.env.CERTBOT_DOMAIN,
|
|
13
|
+
validation = process.env.CERTBOT_VALIDATION,
|
|
14
|
+
token = process.env.CERTBOT_TOKEN,
|
|
15
|
+
remainingChallenges = process.env.CERTBOT_REMAINING_CHALLENGES || 0/*,
|
|
16
|
+
allDomains = process.env.CERTBOT_ALL_DOMAINS.split(',')*/
|
|
17
|
+
;
|
|
18
|
+
(async function() {
|
|
19
|
+
const layout = await (new Layout({ name: 'webflo', flags: {} })).read();
|
|
20
|
+
const acmeDir = Path.join(layout.PUBLIC_DIR, './.well-known/acme-challenge/');
|
|
21
|
+
Fs.mkdirSync(acmeDir, {recursive:true});
|
|
22
|
+
Fs.writeFileSync(Path.join(acmeDir, token), validation);
|
|
23
|
+
})();
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* imports
|
|
5
|
-
*/
|
|
6
|
-
import Fs from 'fs';
|
|
7
|
-
import Path from 'path';
|
|
8
|
-
import Layout from '../../config-pi/deployment/Layout.js';
|
|
9
|
-
|
|
10
|
-
// ------------------------------------------
|
|
11
|
-
|
|
12
|
-
const domain = process.env.CERTBOT_DOMAIN,
|
|
13
|
-
validation = process.env.CERTBOT_VALIDATION,
|
|
14
|
-
token = process.env.CERTBOT_TOKEN,
|
|
15
|
-
authOutput = process.env.CERTBOT_AUTH_OUTPUT,
|
|
16
|
-
remainingChallenges = process.env.CERTBOT_REMAINING_CHALLENGES || 0/*,
|
|
17
|
-
allDomains = process.env.CERTBOT_ALL_DOMAINS.split(',')*/
|
|
18
|
-
;
|
|
19
|
-
(async function() {
|
|
20
|
-
const layout = await (new Layout({ name: 'webflo', flags: {} })).read();
|
|
21
|
-
const acmeFile = Path.join(layout.PUBLIC_DIR, './.well-known/acme-challenge/', token);
|
|
22
|
-
Fs.unlinkSync(acmeFile);
|
|
23
|
-
})();
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* imports
|
|
5
|
+
*/
|
|
6
|
+
import Fs from 'fs';
|
|
7
|
+
import Path from 'path';
|
|
8
|
+
import Layout from '../../config-pi/deployment/Layout.js';
|
|
9
|
+
|
|
10
|
+
// ------------------------------------------
|
|
11
|
+
|
|
12
|
+
const domain = process.env.CERTBOT_DOMAIN,
|
|
13
|
+
validation = process.env.CERTBOT_VALIDATION,
|
|
14
|
+
token = process.env.CERTBOT_TOKEN,
|
|
15
|
+
authOutput = process.env.CERTBOT_AUTH_OUTPUT,
|
|
16
|
+
remainingChallenges = process.env.CERTBOT_REMAINING_CHALLENGES || 0/*,
|
|
17
|
+
allDomains = process.env.CERTBOT_ALL_DOMAINS.split(',')*/
|
|
18
|
+
;
|
|
19
|
+
(async function() {
|
|
20
|
+
const layout = await (new Layout({ name: 'webflo', flags: {} })).read();
|
|
21
|
+
const acmeFile = Path.join(layout.PUBLIC_DIR, './.well-known/acme-challenge/', token);
|
|
22
|
+
Fs.unlinkSync(acmeFile);
|
|
23
|
+
})();
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* imports
|
|
4
|
-
*/
|
|
5
|
-
import Fs from 'fs';
|
|
6
|
-
import { spawn } from 'child_process';
|
|
7
|
-
import { _from as _arrFrom } from '@webqit/util/arr/index.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @description
|
|
11
|
-
*/
|
|
12
|
-
export const desc = {
|
|
13
|
-
generate: 'Generate an SSL cert for a domain or list of domains.',
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Reads SSL from file.
|
|
18
|
-
*
|
|
19
|
-
* @param string allDomains
|
|
20
|
-
*
|
|
21
|
-
* @return object
|
|
22
|
-
*/
|
|
23
|
-
export async function generate(allDomains) {
|
|
24
|
-
const cx = this || {};
|
|
25
|
-
if (!cx.config.runtime?.Server) {
|
|
26
|
-
throw new Error(`The Server configurator "config.runtime.Server" is required in context.`);
|
|
27
|
-
}
|
|
28
|
-
const domains = _arrFrom(allDomains).reduce((all, d) => all.concat(d.split(',')), []).filter(d => d.trim());
|
|
29
|
-
const args = [
|
|
30
|
-
'certonly',
|
|
31
|
-
'--manual',
|
|
32
|
-
'--preferred-challenges', 'http',
|
|
33
|
-
].concat(domains.reduce((all, d) => all.concat('-d', d), []))
|
|
34
|
-
.concat([
|
|
35
|
-
'--manual-auth-hook', 'webflo-certbot-http-auth-hook',
|
|
36
|
-
'--manual-cleanup-hook', 'webflo-certbot-http-cleanup-hook',
|
|
37
|
-
'--debug-challenges',
|
|
38
|
-
'--force-interactive',
|
|
39
|
-
]);
|
|
40
|
-
const child = spawn('certbot', args);
|
|
41
|
-
process.stdin.pipe(child.stdin);
|
|
42
|
-
|
|
43
|
-
child.stdout.on('data', data => {
|
|
44
|
-
if (cx.logger) {
|
|
45
|
-
cx.logger.log('[' + cx.logger.style.keyword('CERTBOT') + '][' + cx.logger.style.var('OUT') + ']:', data + '');
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
child.stderr.on('data', data => {
|
|
50
|
-
if (cx.logger) {
|
|
51
|
-
cx.logger.log('[' + cx.logger.style.keyword('CERTBOT') + '][' + cx.logger.style.err('ERR') + ']:', (data + '').trim());
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
child.on('error', data => {
|
|
56
|
-
cx.logger && cx.logger.error(data);
|
|
57
|
-
process.exit();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
child.on('exit', async exitCode => {
|
|
61
|
-
const serverConfig = new cx.config.runtime.Server(cx);
|
|
62
|
-
const server = await serverConfig.read();
|
|
63
|
-
const domain = domains[0], certDir = `/etc/letsencrypt/live/${domain}`;
|
|
64
|
-
if (!exitCode && cx.flags && (cx.flags['auto-config'] || cx.flags.c)) {
|
|
65
|
-
if (Fs.existsSync(certDir)) {
|
|
66
|
-
cx.logger && cx.logger.log('Automatically configuring the server with the generated cert.');
|
|
67
|
-
if (!server.https) {
|
|
68
|
-
server.https = {};
|
|
69
|
-
}
|
|
70
|
-
server.https.keyfile = `${certDir}/privkey.pem`;
|
|
71
|
-
server.https.certfile = `${certDir}/fullchain.pem`;
|
|
72
|
-
await serverConfig.write(server);
|
|
73
|
-
} else {
|
|
74
|
-
cx.logger && cx.logger.log(`Generated cert files not found in ${certDir}; be sure to configure the server with the valid cert files.`);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
process.exit();
|
|
78
|
-
});
|
|
79
|
-
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* imports
|
|
4
|
+
*/
|
|
5
|
+
import Fs from 'fs';
|
|
6
|
+
import { spawn } from 'child_process';
|
|
7
|
+
import { _from as _arrFrom } from '@webqit/util/arr/index.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @description
|
|
11
|
+
*/
|
|
12
|
+
export const desc = {
|
|
13
|
+
generate: 'Generate an SSL cert for a domain or list of domains.',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Reads SSL from file.
|
|
18
|
+
*
|
|
19
|
+
* @param string allDomains
|
|
20
|
+
*
|
|
21
|
+
* @return object
|
|
22
|
+
*/
|
|
23
|
+
export async function generate(allDomains) {
|
|
24
|
+
const cx = this || {};
|
|
25
|
+
if (!cx.config.runtime?.Server) {
|
|
26
|
+
throw new Error(`The Server configurator "config.runtime.Server" is required in context.`);
|
|
27
|
+
}
|
|
28
|
+
const domains = _arrFrom(allDomains).reduce((all, d) => all.concat(d.split(',')), []).filter(d => d.trim());
|
|
29
|
+
const args = [
|
|
30
|
+
'certonly',
|
|
31
|
+
'--manual',
|
|
32
|
+
'--preferred-challenges', 'http',
|
|
33
|
+
].concat(domains.reduce((all, d) => all.concat('-d', d), []))
|
|
34
|
+
.concat([
|
|
35
|
+
'--manual-auth-hook', 'webflo-certbot-http-auth-hook',
|
|
36
|
+
'--manual-cleanup-hook', 'webflo-certbot-http-cleanup-hook',
|
|
37
|
+
'--debug-challenges',
|
|
38
|
+
'--force-interactive',
|
|
39
|
+
]);
|
|
40
|
+
const child = spawn('certbot', args);
|
|
41
|
+
process.stdin.pipe(child.stdin);
|
|
42
|
+
|
|
43
|
+
child.stdout.on('data', data => {
|
|
44
|
+
if (cx.logger) {
|
|
45
|
+
cx.logger.log('[' + cx.logger.style.keyword('CERTBOT') + '][' + cx.logger.style.var('OUT') + ']:', data + '');
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
child.stderr.on('data', data => {
|
|
50
|
+
if (cx.logger) {
|
|
51
|
+
cx.logger.log('[' + cx.logger.style.keyword('CERTBOT') + '][' + cx.logger.style.err('ERR') + ']:', (data + '').trim());
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
child.on('error', data => {
|
|
56
|
+
cx.logger && cx.logger.error(data);
|
|
57
|
+
process.exit();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
child.on('exit', async exitCode => {
|
|
61
|
+
const serverConfig = new cx.config.runtime.Server(cx);
|
|
62
|
+
const server = await serverConfig.read();
|
|
63
|
+
const domain = domains[0], certDir = `/etc/letsencrypt/live/${domain}`;
|
|
64
|
+
if (!exitCode && cx.flags && (cx.flags['auto-config'] || cx.flags.c)) {
|
|
65
|
+
if (Fs.existsSync(certDir)) {
|
|
66
|
+
cx.logger && cx.logger.log('Automatically configuring the server with the generated cert.');
|
|
67
|
+
if (!server.https) {
|
|
68
|
+
server.https = {};
|
|
69
|
+
}
|
|
70
|
+
server.https.keyfile = `${certDir}/privkey.pem`;
|
|
71
|
+
server.https.certfile = `${certDir}/fullchain.pem`;
|
|
72
|
+
await serverConfig.write(server);
|
|
73
|
+
} else {
|
|
74
|
+
cx.logger && cx.logger.log(`Generated cert files not found in ${certDir}; be sure to configure the server with the valid cert files.`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
process.exit();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
80
|
}
|
package/src/services-pi/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import * as cert from './cert/index.js';
|
|
6
|
-
|
|
7
|
-
export {
|
|
8
|
-
cert,
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import * as cert from './cert/index.js';
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
cert,
|
|
9
9
|
}
|
package/src/static-pi/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
import * as client from './client/index.js';
|
|
5
|
-
import * as server from './server/index.js';
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export {
|
|
9
|
-
//client,
|
|
10
|
-
//server,
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
import * as client from './client/index.js';
|
|
5
|
+
import * as server from './server/index.js';
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
//client,
|
|
10
|
+
//server,
|
|
11
11
|
}
|
package/src/webflo.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @imports
|
|
5
|
-
*/
|
|
6
|
-
import Url from 'url';
|
|
7
|
-
import Path from 'path';
|
|
8
|
-
import { jsonFile } from '@webqit/backpack/src/dotfile/index.js';
|
|
9
|
-
import { Logger, Cli } from '@webqit/backpack';
|
|
10
|
-
import * as WebfloPI from './index.js';
|
|
11
|
-
|
|
12
|
-
const dirSelf = Path.dirname(Url.fileURLToPath(import.meta.url));
|
|
13
|
-
const webfloJson = jsonFile.read(Path.join(dirSelf, '../package.json'));
|
|
14
|
-
const appJson = jsonFile.read('./package.json');
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @cx
|
|
18
|
-
*/
|
|
19
|
-
const cx = WebfloPI.Context.create({
|
|
20
|
-
meta: { title: webfloJson.title, version: webfloJson.version },
|
|
21
|
-
app: { title: appJson.title, version: appJson.version },
|
|
22
|
-
logger: Logger,
|
|
23
|
-
config: WebfloPI.config,
|
|
24
|
-
middlewares: [ WebfloPI.deployment.origins.webhook ],
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @cli
|
|
29
|
-
*/
|
|
30
|
-
const cli = new Cli(WebfloPI);
|
|
31
|
-
await cli.exec(cx);
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @imports
|
|
5
|
+
*/
|
|
6
|
+
import Url from 'url';
|
|
7
|
+
import Path from 'path';
|
|
8
|
+
import { jsonFile } from '@webqit/backpack/src/dotfile/index.js';
|
|
9
|
+
import { Logger, Cli } from '@webqit/backpack';
|
|
10
|
+
import * as WebfloPI from './index.js';
|
|
11
|
+
|
|
12
|
+
const dirSelf = Path.dirname(Url.fileURLToPath(import.meta.url));
|
|
13
|
+
const webfloJson = jsonFile.read(Path.join(dirSelf, '../package.json'));
|
|
14
|
+
const appJson = jsonFile.read('./package.json');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @cx
|
|
18
|
+
*/
|
|
19
|
+
const cx = WebfloPI.Context.create({
|
|
20
|
+
meta: { title: webfloJson.title, version: webfloJson.version },
|
|
21
|
+
app: { title: appJson.title, version: appJson.version },
|
|
22
|
+
logger: Logger,
|
|
23
|
+
config: WebfloPI.config,
|
|
24
|
+
middlewares: [ WebfloPI.deployment.origins.webhook ],
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @cli
|
|
29
|
+
*/
|
|
30
|
+
const cli = new Cli(WebfloPI);
|
|
31
|
+
await cli.exec(cx);
|
package/test/index.test.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import { config, runtime, Context } from '../src/index.js';
|
|
6
|
-
|
|
7
|
-
let client = {
|
|
8
|
-
handle: function( httpEvent ) {
|
|
9
|
-
return new httpEvent.Response({ abcd: '1234' }, {
|
|
10
|
-
status: 302,
|
|
11
|
-
headers: {
|
|
12
|
-
//location: '/dddd',
|
|
13
|
-
cookies: {
|
|
14
|
-
cookie1: { value: 'value1' },
|
|
15
|
-
cookie2: { value: 'value2' },
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const cx = Context.create( { config: config, } );
|
|
23
|
-
const clientCallback = ( _cx, hostName, defaultClientCallback ) => client;
|
|
24
|
-
const app = await runtime.server.start.call( cx, clientCallback );
|
|
25
|
-
|
|
26
|
-
const response = await app.go( 'http://localhost/', { headers: { range: 'bytes=0-5, 6' } } );
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import { config, runtime, Context } from '../src/index.js';
|
|
6
|
+
|
|
7
|
+
let client = {
|
|
8
|
+
handle: function( httpEvent ) {
|
|
9
|
+
return new httpEvent.Response({ abcd: '1234' }, {
|
|
10
|
+
status: 302,
|
|
11
|
+
headers: {
|
|
12
|
+
//location: '/dddd',
|
|
13
|
+
cookies: {
|
|
14
|
+
cookie1: { value: 'value1' },
|
|
15
|
+
cookie2: { value: 'value2' },
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const cx = Context.create( { config: config, } );
|
|
23
|
+
const clientCallback = ( _cx, hostName, defaultClientCallback ) => client;
|
|
24
|
+
const app = await runtime.server.start.call( cx, clientCallback );
|
|
25
|
+
|
|
26
|
+
const response = await app.go( 'http://localhost/', { headers: { range: 'bytes=0-5, 6' } } );
|
package/test/site/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
{
|
|
2
|
-
"title": "Webflo Test",
|
|
3
|
-
"type": "module",
|
|
4
|
-
"scripts": {
|
|
5
|
-
"generate": "webflo generate::client --recursive --compression --auto-embed",
|
|
6
|
-
"bundle": "cd public && oohtml bundle --recursive --auto-embed=routes",
|
|
7
|
-
"build": "npm run generate && npm run bundle"
|
|
8
|
-
}
|
|
9
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"title": "Webflo Test",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"generate": "webflo generate::client --recursive --compression --auto-embed",
|
|
6
|
+
"bundle": "cd public && oohtml bundle --recursive --auto-embed=routes",
|
|
7
|
+
"build": "npm run generate && npm run bundle"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
<template
|
|
3
|
-
<img src="/
|
|
4
|
-
</template>
|
|
5
|
-
<template
|
|
1
|
+
|
|
2
|
+
<template def="page-3">
|
|
3
|
+
<img src="/logo-130x130.png" def="logo-130x130.png" />
|
|
4
|
+
</template>
|
|
5
|
+
<template def="page-4">
|
|
6
6
|
</template>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
{
|
|
2
|
-
"page-3": {},
|
|
3
|
-
"page-4": {}
|
|
1
|
+
{
|
|
2
|
+
"page-3": {},
|
|
3
|
+
"page-4": {}
|
|
4
4
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/** @webqit/webflo */
|
|
2
|
-
var{start:e}=WebQit.Webflo,r={},o={bundle_filename:"bundle.js",public_base_url:"/",spa_routing:!0,oohtml_support:"full",service_worker_support:!0,worker_scope:"/",worker_filename:"worker.js",routing:{root:"/",subroots:["/page-2","/page-4/subpage"],targets:2}};e.call({layout:r,params:o});
|
|
1
|
+
/** @webqit/webflo */
|
|
2
|
+
var{start:e}=WebQit.Webflo,r={},o={bundle_filename:"bundle.js",public_base_url:"/",spa_routing:!0,oohtml_support:"full",service_worker_support:!0,worker_scope:"/",worker_filename:"worker.js",routing:{root:"/",subroots:["/page-2","/page-4/subpage"],targets:2}};e.call({layout:r,params:o});
|