@webqit/webflo 0.8.76 → 0.9.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/package.json +5 -12
- package/src/Cli.js +131 -0
- package/src/Configurator.js +97 -0
- package/src/Context.js +76 -0
- package/src/config-pi/deployment/Env.js +69 -0
- package/src/config-pi/deployment/Layout.js +65 -0
- package/src/config-pi/deployment/Origins.js +133 -0
- package/src/config-pi/deployment/Virtualization.js +65 -0
- package/src/config-pi/deployment/index.js +18 -0
- package/src/config-pi/index.js +16 -0
- package/src/config-pi/runtime/Client.js +59 -0
- package/src/config-pi/runtime/Server.js +174 -0
- package/src/config-pi/runtime/client/Worker.js +117 -0
- package/src/config-pi/runtime/client/index.js +12 -0
- package/src/config-pi/runtime/index.js +18 -0
- package/src/config-pi/runtime/server/Headers.js +90 -0
- package/src/config-pi/runtime/server/Redirects.js +108 -0
- package/src/config-pi/runtime/server/index.js +14 -0
- package/src/config-pi/static/Manifest.js +321 -0
- package/src/config-pi/static/Ssg.js +72 -0
- package/src/config-pi/static/index.js +14 -0
- package/src/deployment-pi/index.js +10 -0
- package/src/{services → deployment-pi}/origins/index.js +88 -58
- package/src/index.js +14 -147
- package/src/{runtime → runtime-pi}/Router.js +19 -19
- package/src/runtime-pi/client/Context.js +7 -0
- package/src/{runtime → runtime-pi}/client/Router.js +2 -2
- package/src/{runtime/client/Navigator.js → runtime-pi/client/Runtime.js} +143 -102
- package/src/runtime-pi/client/RuntimeClient.js +114 -0
- package/src/{runtime → runtime-pi}/client/Storage.js +8 -7
- package/src/{runtime → runtime-pi}/client/Url.js +2 -6
- package/src/{runtime/client/WorkerClient.js → runtime-pi/client/WorkerComm.js} +2 -2
- package/src/runtime-pi/client/generate.js +242 -0
- package/src/runtime-pi/client/generate.oohtml.js +7 -0
- package/src/runtime-pi/client/index.js +18 -0
- package/src/runtime-pi/client/whatwag.js +27 -0
- package/src/runtime-pi/client/worker/Context.js +7 -0
- package/src/runtime-pi/client/worker/Worker.js +243 -0
- package/src/runtime-pi/client/worker/WorkerClient.js +46 -0
- package/src/runtime-pi/client/worker/index.js +18 -0
- package/src/runtime-pi/index.js +14 -0
- package/src/runtime-pi/server/Context.js +16 -0
- package/src/{runtime → runtime-pi}/server/Router.js +6 -6
- package/src/runtime-pi/server/Runtime.js +531 -0
- package/src/runtime-pi/server/RuntimeClient.js +102 -0
- package/src/runtime-pi/server/index.js +41 -0
- package/src/runtime-pi/server/whatwag.js +35 -0
- package/src/{runtime → runtime-pi}/util.js +0 -0
- package/src/{runtime/_FormData.js → runtime-pi/xFormData.js} +2 -2
- package/src/{runtime/_Headers.js → runtime-pi/xHeaders.js} +4 -4
- package/src/runtime-pi/xHttpEvent.js +93 -0
- package/src/runtime-pi/xHttpMessage.js +179 -0
- package/src/runtime-pi/xRequest.js +67 -0
- package/src/runtime-pi/xRequestHeaders.js +95 -0
- package/src/runtime-pi/xResponse.js +62 -0
- package/src/{runtime/_ResponseHeaders.js → runtime-pi/xResponseHeaders.js} +38 -18
- package/src/{runtime/_URL.js → runtime-pi/xURL.js} +4 -4
- package/src/runtime-pi/xfetch.js +7 -0
- package/src/{services → services-pi}/certbot/http-auth-hook.js +0 -0
- package/src/{services → services-pi}/certbot/http-cleanup-hook.js +0 -0
- package/src/{services → services-pi}/certbot/index.js +21 -15
- package/src/services-pi/index.js +9 -0
- package/src/static-pi/index.js +11 -0
- package/src/webflo.js +33 -0
- package/test/index.test.js +26 -0
- package/src/build/client/index.js +0 -261
- package/src/build/index.js +0 -5
- package/src/config/client.js +0 -191
- package/src/config/headers.js +0 -121
- package/src/config/index.js +0 -14
- package/src/config/layout.js +0 -83
- package/src/config/manifest.js +0 -341
- package/src/config/origins.js +0 -165
- package/src/config/prerendering.js +0 -100
- package/src/config/redirects.js +0 -137
- package/src/config/server.js +0 -201
- package/src/config/variables.js +0 -102
- package/src/config/vhosts.js +0 -93
- package/src/runtime/_MessageStream.js +0 -195
- package/src/runtime/_NavigationEvent.js +0 -91
- package/src/runtime/_Request.js +0 -61
- package/src/runtime/_RequestHeaders.js +0 -72
- package/src/runtime/_Response.js +0 -56
- package/src/runtime/client/Cache.js +0 -38
- package/src/runtime/client/Http.js +0 -225
- package/src/runtime/client/NavigationEvent.js +0 -21
- package/src/runtime/client/Runtime.js +0 -126
- package/src/runtime/client/StdRequest.js +0 -74
- package/src/runtime/client/Worker.js +0 -312
- package/src/runtime/client/WorkerComm.js +0 -183
- package/src/runtime/client/effects/sounds.js +0 -64
- package/src/runtime/index.js +0 -5
- package/src/runtime/server/NavigationEvent.js +0 -39
- package/src/runtime/server/Runtime.js +0 -593
- package/src/runtime/server/index.js +0 -183
- package/src/runtime/server/index.mjs +0 -10
- package/src/services/index.js +0 -6
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @imports
|
|
4
|
+
*/
|
|
5
|
+
import xHttpMessage, { encodeBody } from './xHttpMessage.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The xResponse Mixin
|
|
9
|
+
*/
|
|
10
|
+
const xResponse = (whatwagResponse, Headers, FormData) => class extends xHttpMessage(whatwagResponse, Headers, FormData) {
|
|
11
|
+
|
|
12
|
+
// construct
|
|
13
|
+
constructor(body = null, init = {}) {
|
|
14
|
+
let bodyAttrs = {}, isResponseInput;
|
|
15
|
+
if (arguments.length) {
|
|
16
|
+
if (body instanceof whatwagResponse) {
|
|
17
|
+
isResponseInput = body;
|
|
18
|
+
// Inherit init
|
|
19
|
+
init = { status: body.status, statusText: body.statusText, headers: body.headers, ...init };
|
|
20
|
+
if (body.status === 0) delete init.status;
|
|
21
|
+
// Inherit bodyAttrs and body
|
|
22
|
+
bodyAttrs = body.bodyAttrs || {};
|
|
23
|
+
body = body.body;
|
|
24
|
+
} else {
|
|
25
|
+
bodyAttrs = encodeBody(body, FormData);
|
|
26
|
+
body = bodyAttrs.body;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
super(body, init, bodyAttrs);
|
|
30
|
+
if (isResponseInput) {
|
|
31
|
+
// Through the backdoor
|
|
32
|
+
this.attrs.url = isResponseInput.url;
|
|
33
|
+
this.attrs.ok = isResponseInput.ok;
|
|
34
|
+
this.attrs.status = isResponseInput.status; // In case it was earlier deleted
|
|
35
|
+
this.attrs.type = isResponseInput.type;
|
|
36
|
+
this.attrs.redirected = isResponseInput.redirected;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get ok() {
|
|
41
|
+
return 'ok' in this.attrs ? this.attrs.ok : super.ok;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get status() {
|
|
45
|
+
return 'status' in this.attrs ? this.attrs.status : super.status;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get statusText() {
|
|
49
|
+
return 'statusText' in this.attrs ? this.attrs.statusText : super.statusText;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get type() {
|
|
53
|
+
return 'type' in this.attrs ? this.attrs.type : super.type;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get redirected() {
|
|
57
|
+
return 'redirected' in this.attrs ? this.attrs.redirected : super.redirected;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export default xResponse;
|
|
@@ -4,13 +4,49 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { _after, _beforeLast } from "@webqit/util/str/index.js";
|
|
6
6
|
import { _isString, _getType, _isObject } from "@webqit/util/js/index.js";
|
|
7
|
-
import _Headers from './
|
|
7
|
+
import _Headers from './xHeaders.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* The _Headers Mixin
|
|
11
11
|
*/
|
|
12
12
|
const _ResponseHeaders = NativeHeaders => class extends _Headers(NativeHeaders) {
|
|
13
13
|
|
|
14
|
+
set cookies(cookieJar) {
|
|
15
|
+
if (!_isObject(cookieJar)) {
|
|
16
|
+
throw new Error(`The "cookies" response directive cannot be of type: ${_getType(cookieJar)}`);
|
|
17
|
+
}
|
|
18
|
+
for (let cookieName in cookieJar) {
|
|
19
|
+
let cookieBody = cookieJar[cookieName];
|
|
20
|
+
if (_isObject(cookieBody)) {
|
|
21
|
+
let attrsArr = [ cookieBody.value ];
|
|
22
|
+
for (let attrName in cookieBody) {
|
|
23
|
+
if (attrName === 'value') continue;
|
|
24
|
+
let _attrName = attrName[0].toUpperCase() + attrName.substring(1);
|
|
25
|
+
if (_attrName === 'MaxAge') { _attrName = 'Max-Age' };
|
|
26
|
+
attrsArr.push(cookieBody[attrName] === true ? _attrName : `${_attrName}=${cookieBody[attrName]}`);
|
|
27
|
+
}
|
|
28
|
+
cookieBody = attrsArr.join('; ');
|
|
29
|
+
}
|
|
30
|
+
this.append('Set-Cookie', `${cookieName}=${cookieBody}`);
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get cookies() {
|
|
36
|
+
const cookiesStr = this.get('Set-Cookie');
|
|
37
|
+
return cookiesStr && cookiesStr.split(',').reduce((cookieJar, str) => {
|
|
38
|
+
let [ cookieDefinition, attrsStr ] = str.split(';');
|
|
39
|
+
let [ cookieName, cookieValue ] = cookieDefinition.trim().split('=');
|
|
40
|
+
cookieJar[cookieName] = { value: cookieValue, };
|
|
41
|
+
if (attrsStr) {
|
|
42
|
+
(attrsStr || '').split(/\;/g).map(attrStr => attrStr.trim().split('=')).forEach(attrsArr => {
|
|
43
|
+
cookieJar[cookieName][attrsArr[0][0].toLowerCase() + attrsArr[0].substring(1).replace('-', '')] = attrsArr.length === 1 ? true : attrsArr[1];
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return cookieJar;
|
|
47
|
+
}, {});
|
|
48
|
+
}
|
|
49
|
+
|
|
14
50
|
set contentRange(value) {
|
|
15
51
|
if (Array.isArray(value)) {
|
|
16
52
|
if ((value.length === 2 && !value[0].includes('-')) || value.length < 2) {
|
|
@@ -18,28 +54,12 @@ const _ResponseHeaders = NativeHeaders => class extends _Headers(NativeHeaders)
|
|
|
18
54
|
}
|
|
19
55
|
return this.set('Content-Range', `bytes ${value.join('/')}`);
|
|
20
56
|
}
|
|
21
|
-
if (!this.has('Accept-Ranges')) {
|
|
22
|
-
this.set('Accept-Ranges', 'bytes');
|
|
23
|
-
}
|
|
24
57
|
return this.set('Content-Range', value);
|
|
25
58
|
}
|
|
26
59
|
|
|
27
60
|
get contentRange() {
|
|
28
61
|
const value = this.get('Content-Range');
|
|
29
|
-
|
|
30
|
-
return _after(value, 'bytes ').split('/');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
set cookies(cookieStr) {
|
|
34
|
-
if (!_isObject(cookieJar)) {
|
|
35
|
-
throw new Error(`The "cookies" response directive does not support the type: ${_getType(cookieStr)}`);
|
|
36
|
-
}
|
|
37
|
-
this.set('Set-Cookie', cookieStr);
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
get cookies() {
|
|
42
|
-
return this.get('Set-Cookie');
|
|
62
|
+
return value && _after(value, 'bytes ').split('/');
|
|
43
63
|
}
|
|
44
64
|
|
|
45
65
|
set cors(value) {
|
|
@@ -8,11 +8,11 @@ import { wwwFormUnserialize, wwwFormSerialize } from './util.js';
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* ---------------------------
|
|
11
|
-
* The
|
|
11
|
+
* The xURL Mixin
|
|
12
12
|
* ---------------------------
|
|
13
13
|
*/
|
|
14
|
-
const
|
|
15
|
-
const URL = class extends
|
|
14
|
+
const xURL = whatwagURL => {
|
|
15
|
+
const URL = class extends whatwagURL {
|
|
16
16
|
|
|
17
17
|
// constructor
|
|
18
18
|
constructor(...args) {
|
|
@@ -108,4 +108,4 @@ var _strictEven = (a, b) => {
|
|
|
108
108
|
return a === b;
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
-
export default
|
|
111
|
+
export default xURL;
|
|
File without changes
|
|
File without changes
|
|
@@ -4,27 +4,27 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import Fs from 'fs';
|
|
6
6
|
import { spawn } from 'child_process';
|
|
7
|
-
import _arrFrom from '@webqit/util/arr/
|
|
8
|
-
import * as _server from '../../config/server.js';
|
|
7
|
+
import { _from as _arrFrom } from '@webqit/util/arr/index.js';
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* @description
|
|
12
11
|
*/
|
|
13
12
|
export const desc = {
|
|
14
|
-
generate: '
|
|
13
|
+
generate: 'Generate an SSL cert for a domain or list of domains.',
|
|
15
14
|
};
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
17
|
* Reads SSL from file.
|
|
19
18
|
*
|
|
20
|
-
* @param Ui Ui
|
|
21
19
|
* @param string allDomains
|
|
22
|
-
* @param object flags
|
|
23
|
-
* @param object layout
|
|
24
20
|
*
|
|
25
21
|
* @return object
|
|
26
22
|
*/
|
|
27
|
-
export async function generate(
|
|
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
28
|
const domains = _arrFrom(allDomains).reduce((all, d) => all.concat(d.split(',')), []).filter(d => d.trim());
|
|
29
29
|
const args = [
|
|
30
30
|
'certonly',
|
|
@@ -41,34 +41,40 @@ export async function generate(Ui, allDomains, flags = {}, layout = {}) {
|
|
|
41
41
|
process.stdin.pipe(child.stdin);
|
|
42
42
|
|
|
43
43
|
child.stdout.on('data', data => {
|
|
44
|
-
|
|
44
|
+
if (cx.logger) {
|
|
45
|
+
cx.logger.log('[' + cx.logger.style.keyword('CERTBOT') + '][' + cx.logger.style.var('OUT') + ']:', data + '');
|
|
46
|
+
}
|
|
45
47
|
});
|
|
46
48
|
|
|
47
49
|
child.stderr.on('data', data => {
|
|
48
|
-
|
|
50
|
+
if (cx.logger) {
|
|
51
|
+
cx.logger.log('[' + cx.logger.style.keyword('CERTBOT') + '][' + cx.logger.style.err('ERR') + ']:', (data + '').trim());
|
|
52
|
+
}
|
|
49
53
|
});
|
|
50
54
|
|
|
51
55
|
child.on('error', data => {
|
|
52
|
-
|
|
56
|
+
cx.logger && cx.logger.error(data);
|
|
53
57
|
process.exit();
|
|
54
58
|
});
|
|
55
59
|
|
|
56
60
|
child.on('exit', async exitCode => {
|
|
57
|
-
const
|
|
61
|
+
const serverConfig = new cx.config.runtime.Server(cx);
|
|
62
|
+
const server = await serverConfig.read();
|
|
58
63
|
const domain = domains[0], certDir = `/etc/letsencrypt/live/${domain}`;
|
|
59
|
-
if (!exitCode && (flags['auto-config'] || flags.c)) {
|
|
64
|
+
if (!exitCode && cx.flags && (cx.flags['auto-config'] || cx.flags.c)) {
|
|
60
65
|
if (Fs.existsSync(certDir)) {
|
|
61
|
-
|
|
66
|
+
cx.logger && cx.logger.log('Automatically configuring the server with the generated cert.');
|
|
62
67
|
if (!server.https) {
|
|
63
68
|
server.https = {};
|
|
64
69
|
}
|
|
65
70
|
server.https.keyfile = `${certDir}/privkey.pem`;
|
|
66
71
|
server.https.certfile = `${certDir}/fullchain.pem`;
|
|
67
|
-
await
|
|
72
|
+
await serverConfig.write(server);
|
|
68
73
|
} else {
|
|
69
|
-
|
|
74
|
+
cx.logger && cx.logger.log(`Generated cert files not found in ${certDir}; be sure to configure the server with the valid cert files.`);
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
process.exit();
|
|
73
78
|
});
|
|
79
|
+
|
|
74
80
|
}
|
package/src/webflo.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @imports
|
|
5
|
+
*/
|
|
6
|
+
import Url from 'url';
|
|
7
|
+
import Path from 'path';
|
|
8
|
+
import { read as readJsonFile } from '@webqit/backpack/src/dotfiles/DotJson.js';
|
|
9
|
+
import logger from '@webqit/backpack/src/cli/Ui.js';
|
|
10
|
+
import * as WebfloPI from './index.js';
|
|
11
|
+
import Context from './Context.js';
|
|
12
|
+
import Cli from './Cli.js';
|
|
13
|
+
|
|
14
|
+
const dirSelf = Path.dirname(Url.fileURLToPath(import.meta.url));
|
|
15
|
+
const webfloJson = readJsonFile(Path.join(dirSelf, '../package.json'));
|
|
16
|
+
const appJson = readJsonFile('./package.json');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @cx
|
|
20
|
+
*/
|
|
21
|
+
const cx = Context.create({
|
|
22
|
+
webflo: { title: webfloJson.title, version: webfloJson.version },
|
|
23
|
+
app: { title: appJson.title, version: appJson.version },
|
|
24
|
+
logger,
|
|
25
|
+
config: WebfloPI.config,
|
|
26
|
+
middlewares: [ WebfloPI.deployment.origins.webhook, ],
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @cli
|
|
31
|
+
*/
|
|
32
|
+
const cli = new Cli(WebfloPI);
|
|
33
|
+
await cli.exec(cx);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @imports
|
|
3
|
+
*/
|
|
4
|
+
import Context from "../src/Context.js";
|
|
5
|
+
import * as WebfloPI 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: WebfloPI.config, });
|
|
23
|
+
const clientCallback = (_cx, hostName, defaultClientCallback) => client;
|
|
24
|
+
const app = await WebfloPI.runtime.server.start.call(cx, clientCallback);
|
|
25
|
+
|
|
26
|
+
const response = await app.go('http://localhost/', { headers: { range: 'bytes=0-5, 6' } } );
|
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* imports
|
|
4
|
-
*/
|
|
5
|
-
import Fs from 'fs';
|
|
6
|
-
import Url from 'url';
|
|
7
|
-
import Path from 'path';
|
|
8
|
-
import Webpack from 'webpack';
|
|
9
|
-
import { _beforeLast } from '@webqit/util/str/index.js';
|
|
10
|
-
import { _isObject, _isArray, _isEmpty } from '@webqit/util/js/index.js';
|
|
11
|
-
import * as DotJs from '@webqit/backpack/src/dotfiles/DotJs.js';
|
|
12
|
-
import * as client from '../../config/client.js'
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @description
|
|
17
|
-
*/
|
|
18
|
-
export const desc = {
|
|
19
|
-
build: 'Creates the application Client Build.',
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @build
|
|
24
|
-
*/
|
|
25
|
-
export async function build(Ui, flags = {}, layout = {}) {
|
|
26
|
-
|
|
27
|
-
const config = await client.read(flags, layout);
|
|
28
|
-
// Consistent forward slashing
|
|
29
|
-
const forwardSlash = str => str.replace(/\\/g, '/');
|
|
30
|
-
var modulesDir = forwardSlash(Url.fileURLToPath(Path.join(import.meta.url, '../../../runtime/client')));
|
|
31
|
-
|
|
32
|
-
var workerDirSplit = Path.resolve(layout.WORKER_DIR).replace(/\\/g, '/').split('/');
|
|
33
|
-
var workerParams = config.worker || {};
|
|
34
|
-
const workerBundlingConfig = workerParams.bundling || {};
|
|
35
|
-
|
|
36
|
-
var clientDirSplit = Path.resolve(layout.CLIENT_DIR).replace(/\\/g, '/').split('/');
|
|
37
|
-
var clientParams = config; // Yes root config object
|
|
38
|
-
const clientBundlingConfig = clientParams.bundling || {};
|
|
39
|
-
|
|
40
|
-
var waiting;
|
|
41
|
-
|
|
42
|
-
// -------------------
|
|
43
|
-
// Create the Service Worker file
|
|
44
|
-
// -------------------
|
|
45
|
-
|
|
46
|
-
if (!_isEmpty(workerParams)) {
|
|
47
|
-
|
|
48
|
-
Ui.log('');
|
|
49
|
-
Ui.title(`SERVICE WORKER BUILD`);
|
|
50
|
-
|
|
51
|
-
const workerBuild = { imports: {}, code: [], };
|
|
52
|
-
workerBuild.imports[modulesDir + '/Worker.js'] = 'Worker';
|
|
53
|
-
|
|
54
|
-
// ------------------
|
|
55
|
-
// >> Routes mapping
|
|
56
|
-
buildRoutes(workerBuild, Ui, Path.resolve(layout.WORKER_DIR), 'Worker-Side Routing:');
|
|
57
|
-
workerBuild.code.push(``);
|
|
58
|
-
workerBuild.code.push(`// >> Worker Params`);
|
|
59
|
-
buildParams(workerBuild, workerParams, 'params');
|
|
60
|
-
workerBuild.code.push(``);
|
|
61
|
-
workerBuild.code.push(`// >> Worker Instantiation`);
|
|
62
|
-
workerBuild.code.push(`Worker.call(null, layout, params);`);
|
|
63
|
-
// ------------------
|
|
64
|
-
|
|
65
|
-
// ------------------
|
|
66
|
-
// >> Write to file...
|
|
67
|
-
workerBundlingConfig.intermediate = workerBundlingConfig.intermediate || `${clientDirSplit.join('/')}/worker.js`;
|
|
68
|
-
workerBundlingConfig.output = workerBundlingConfig.output || {
|
|
69
|
-
filename: 'worker.js',
|
|
70
|
-
path: Path.resolve(layout.PUBLIC_DIR),
|
|
71
|
-
};
|
|
72
|
-
waiting = Ui.waiting(Ui.f`Writing the Service Worker file: ${workerBundlingConfig.intermediate}`);
|
|
73
|
-
waiting.start();
|
|
74
|
-
DotJs.write(workerBuild, workerBundlingConfig.intermediate, 'Service Worker File');
|
|
75
|
-
waiting.stop();
|
|
76
|
-
Ui.info(Ui.f`Service Worker file: ${workerBundlingConfig.intermediate}`);
|
|
77
|
-
// ------------------
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// -------------------
|
|
81
|
-
// Create the Client file
|
|
82
|
-
// -------------------
|
|
83
|
-
|
|
84
|
-
Ui.log('');
|
|
85
|
-
Ui.title(`CLIENT BUILD`);
|
|
86
|
-
|
|
87
|
-
const clientBuild = { imports: {}, code: [], };
|
|
88
|
-
clientBuild.imports[modulesDir + '/Runtime.js'] = 'Runtime';
|
|
89
|
-
|
|
90
|
-
// ------------------
|
|
91
|
-
// >> Routes mapping
|
|
92
|
-
buildRoutes(clientBuild, Ui, Path.resolve(layout.CLIENT_DIR), 'Client-Side Routing:');
|
|
93
|
-
clientBuild.code.push(``);
|
|
94
|
-
clientBuild.code.push(`// >> Runtime Params`);
|
|
95
|
-
buildParams(clientBuild, clientParams, 'params');
|
|
96
|
-
clientBuild.code.push(``);
|
|
97
|
-
clientBuild.code.push(`// >> Runtime Instantiation`);
|
|
98
|
-
clientBuild.code.push(`Runtime.call(null, layout, params);`);
|
|
99
|
-
// ------------------
|
|
100
|
-
|
|
101
|
-
// ------------------
|
|
102
|
-
// >> Write to file...
|
|
103
|
-
clientBundlingConfig.intermediate = clientBundlingConfig.intermediate || clientDirSplit.join('/') + '/bundle.js';
|
|
104
|
-
clientBundlingConfig.output = clientBundlingConfig.output || {
|
|
105
|
-
filename: 'bundle.js',
|
|
106
|
-
path: Path.resolve(layout.PUBLIC_DIR),
|
|
107
|
-
};
|
|
108
|
-
waiting = Ui.waiting(`Writing the client entry file: ${clientBundlingConfig.intermediate}`);
|
|
109
|
-
waiting.start();
|
|
110
|
-
DotJs.write(clientBuild, clientBundlingConfig.intermediate, 'Runtime Build File');
|
|
111
|
-
waiting.stop();
|
|
112
|
-
Ui.info(Ui.f`Runtime Build file: ${clientBundlingConfig.intermediate}`);
|
|
113
|
-
// ------------------
|
|
114
|
-
|
|
115
|
-
// -------------------
|
|
116
|
-
// Run webpack
|
|
117
|
-
// -------------------
|
|
118
|
-
|
|
119
|
-
if (clientParams.bundling || workerParams.bundling) {
|
|
120
|
-
Ui.log('');
|
|
121
|
-
Ui.title(`BUNDLES`);
|
|
122
|
-
}
|
|
123
|
-
if (workerParams.bundling !== false) {
|
|
124
|
-
await createBundle(Ui, workerBundlingConfig, 'Bundling the Service Worker Build file');
|
|
125
|
-
}
|
|
126
|
-
if (clientParams.bundling !== false) {
|
|
127
|
-
clientBundlingConfig.experiments = clientBundlingConfig.experiments || {};
|
|
128
|
-
if (!('outputModule' in clientBundlingConfig.experiments)) {
|
|
129
|
-
clientBundlingConfig.experiments.outputModule = true;
|
|
130
|
-
clientBundlingConfig.externalsType = 'module';
|
|
131
|
-
}
|
|
132
|
-
if (clientBundlingConfig.experiments.outputModule !== false) {
|
|
133
|
-
clientBundlingConfig.output = clientBundlingConfig.output || {};
|
|
134
|
-
clientBundlingConfig.output.environment = clientBundlingConfig.output.environment || {};
|
|
135
|
-
if (!('module' in clientBundlingConfig.output)) {
|
|
136
|
-
clientBundlingConfig.output.module = true;
|
|
137
|
-
clientBundlingConfig.output.environment.module = true;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
await createBundle(Ui, clientBundlingConfig, 'Bundling the Runtime Build file');
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Creates a bundle using webpack
|
|
147
|
-
*
|
|
148
|
-
* @param {object} config
|
|
149
|
-
* @param {string} desc
|
|
150
|
-
*
|
|
151
|
-
* @return void
|
|
152
|
-
*/
|
|
153
|
-
const createBundle = (Ui, config, desc) => {
|
|
154
|
-
const intermediateFile = config.intermediate;
|
|
155
|
-
config = { ...config };
|
|
156
|
-
if (!config.entry) {
|
|
157
|
-
config.entry = config.intermediate;
|
|
158
|
-
}
|
|
159
|
-
delete config.intermediate;
|
|
160
|
-
return new Promise(resolve => {
|
|
161
|
-
var waiting = Ui.waiting(`${desc} ...`);
|
|
162
|
-
Ui.log('');
|
|
163
|
-
Ui.info(Ui.f`FROM: ${config.entry}`);
|
|
164
|
-
Ui.info(Ui.f`TO: ${config.output.path + '/' + config.output.filename}`);
|
|
165
|
-
Ui.log('');
|
|
166
|
-
waiting.start();
|
|
167
|
-
|
|
168
|
-
// Run
|
|
169
|
-
var compiler = Webpack(config);
|
|
170
|
-
compiler.run((err, stats) => {
|
|
171
|
-
waiting.stop();
|
|
172
|
-
if (err) {
|
|
173
|
-
Ui.title(`Errors!`);
|
|
174
|
-
Ui.error(err);
|
|
175
|
-
}
|
|
176
|
-
Ui.log(stats.toString({
|
|
177
|
-
colors: true,
|
|
178
|
-
}));
|
|
179
|
-
// Remove intermediate build
|
|
180
|
-
Fs.unlinkSync(intermediateFile);
|
|
181
|
-
resolve();
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Initializes a server on the given working directory.
|
|
188
|
-
*
|
|
189
|
-
* @param object params
|
|
190
|
-
*
|
|
191
|
-
* @return void
|
|
192
|
-
*/
|
|
193
|
-
const buildRoutes = (build, Ui, entry, desc) => {
|
|
194
|
-
// -------------------
|
|
195
|
-
// Helper functions
|
|
196
|
-
// -------------------
|
|
197
|
-
// Directory walking
|
|
198
|
-
const walk = (dir, callback) => {
|
|
199
|
-
Fs.readdirSync(dir).forEach(f => {
|
|
200
|
-
let resource = Path.join(dir, f);
|
|
201
|
-
if (Fs.statSync(resource).isDirectory()) {
|
|
202
|
-
walk(resource, callback);
|
|
203
|
-
} else {
|
|
204
|
-
var ext = Path.extname(resource) || '';
|
|
205
|
-
callback(resource, ext);
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
Ui.log('');
|
|
211
|
-
Ui.title(desc);
|
|
212
|
-
|
|
213
|
-
// >> Routes mapping
|
|
214
|
-
build.code.push(`// >> ` + desc);
|
|
215
|
-
build.code.push(`const layout = {};`);
|
|
216
|
-
|
|
217
|
-
var indexCount = 0;
|
|
218
|
-
if (entry && Fs.existsSync(entry)) {
|
|
219
|
-
var clientDirname = entry.replace(/\\/g, '/').split('/').pop();
|
|
220
|
-
walk(entry, (file, ext) => {
|
|
221
|
-
//relativePath = relativePath.replace(/\\/g, '/');
|
|
222
|
-
if (file.replace(/\\/g, '/').endsWith('/index.js')) {
|
|
223
|
-
var relativePath = Path.relative(entry, file).replace(/\\/g, '/');
|
|
224
|
-
// Import code
|
|
225
|
-
var routeName = 'index' + (++ indexCount);
|
|
226
|
-
// IMPORTANT: we;re taking a step back here so that the parent-child relationship for
|
|
227
|
-
// the directories be involved
|
|
228
|
-
build.imports[`../${clientDirname}/${relativePath}`] = '* as ' + routeName;
|
|
229
|
-
// Definition code
|
|
230
|
-
var routePath = _beforeLast('/' + relativePath, '/index.js');
|
|
231
|
-
build.code.push(`layout['${routePath || '/'}'] = ${routeName};`);
|
|
232
|
-
// Show
|
|
233
|
-
Ui.log(`> ./${relativePath}`);
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
if (!indexCount) {
|
|
238
|
-
Ui.log(`> (none)`);
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
const buildParams = (build, params, varName = null, indentation = 0) => {
|
|
243
|
-
if (varName) build.code.push(`const ${varName} = {`);
|
|
244
|
-
Object.keys(params).forEach(name => {
|
|
245
|
-
var _name = ` ${' '.repeat(indentation)}${(_isArray(params) ? '' : (name.includes(' ') ? `'${name}'` : name) + ': ')}`;
|
|
246
|
-
if ([ 'boolean', 'number' ].includes(typeof params[name])) {
|
|
247
|
-
build.code.push(`${_name}${params[name]},`);
|
|
248
|
-
} else if (_isArray(params[name])) {
|
|
249
|
-
build.code.push(`${_name}[`);
|
|
250
|
-
buildParams(build, params[name], null, indentation + 1);
|
|
251
|
-
build.code.push(` ${' '.repeat(indentation)}],`);
|
|
252
|
-
} else if (_isObject(params[name])) {
|
|
253
|
-
build.code.push(`${_name}{`);
|
|
254
|
-
buildParams(build, params[name], null, indentation + 1);
|
|
255
|
-
build.code.push(` ${' '.repeat(indentation)}},`);
|
|
256
|
-
} else {
|
|
257
|
-
build.code.push(`${_name}'${params[name]}',`);
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
if (varName) build.code.push(`};`);
|
|
261
|
-
};
|