@webqit/webflo 0.10.1 → 0.10.4
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 +68 -0
- package/package.json +2 -2
- package/src/Context.js +7 -3
- package/src/config-pi/deployment/Env.js +2 -2
- package/src/config-pi/deployment/Layout.js +2 -2
- package/src/config-pi/deployment/Origins.js +2 -2
- package/src/config-pi/deployment/Virtualization.js +2 -2
- package/src/config-pi/runtime/Client.js +2 -2
- package/src/config-pi/runtime/Server.js +2 -2
- package/src/config-pi/runtime/client/Worker.js +2 -2
- package/src/config-pi/runtime/server/Headers.js +2 -2
- package/src/config-pi/runtime/server/Redirects.js +2 -2
- package/src/config-pi/static/Manifest.js +2 -2
- package/src/config-pi/static/Ssg.js +2 -2
- package/src/runtime-pi/client/Runtime.js +1 -1
- package/src/runtime-pi/client/generate.js +3 -3
- package/src/runtime-pi/client/worker/Worker.js +22 -20
- package/src/runtime-pi/xHttpMessage.js +1 -1
- package/src/runtime-pi/xRequest.js +7 -0
- package/src/webflo.js +7 -9
- package/src/Cli.js +0 -131
- package/src/Configurator.js +0 -97
package/README.md
CHANGED
|
@@ -7,3 +7,71 @@
|
|
|
7
7
|
<span class="badge-patreon"><a href="https://patreon.com/ox_harris" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span>
|
|
8
8
|
|
|
9
9
|
<!-- /BADGES -->
|
|
10
|
+
|
|
11
|
+
The execution model of functional programs is fundamentally different from how we like to think in a procedural model.
|
|
12
|
+
If I did the following:
|
|
13
|
+
|
|
14
|
+
let [ valueA, setValueA ] = createSignal(10);
|
|
15
|
+
let [ valueB, setValueB ] = createSignal();
|
|
16
|
+
createEffect(() => setValueB(valueA() * 2));
|
|
17
|
+
|
|
18
|
+
createEffect(() => console.log( valueB() ));
|
|
19
|
+
|
|
20
|
+
createEffect(() => {
|
|
21
|
+
if (someCondition()) {
|
|
22
|
+
setValueA(20);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
createEffect(() => console.log( valueB() ));
|
|
28
|
+
|
|
29
|
+
You'll see now that I have two effect blocks reacting both ABOVE and BELOW the point of mutation.
|
|
30
|
+
|
|
31
|
+
Whereas if I did the same procedurally:
|
|
32
|
+
|
|
33
|
+
function** fn() {
|
|
34
|
+
let a = 10;
|
|
35
|
+
let b = a * 2;
|
|
36
|
+
|
|
37
|
+
console.log(b);
|
|
38
|
+
|
|
39
|
+
if (someCondition) {
|
|
40
|
+
a = 20;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log(b);
|
|
44
|
+
}
|
|
45
|
+
fn();
|
|
46
|
+
fn.thread( [ 'someCondition' ] );
|
|
47
|
+
|
|
48
|
+
I'd expect only the console.log() expression BELOW the point of mutation to react. So, code within Subscript Functions don't just look procedural, but work procedurally.
|
|
49
|
+
|
|
50
|
+
function** fn() {
|
|
51
|
+
let result = (a || b) && consequentExpr || alternateExpr;
|
|
52
|
+
}
|
|
53
|
+
fn();
|
|
54
|
+
|
|
55
|
+
@mathias
|
|
56
|
+
|
|
57
|
+
@tomayac
|
|
58
|
+
|
|
59
|
+
@domenic
|
|
60
|
+
|
|
61
|
+
@jaffathecake
|
|
62
|
+
|
|
63
|
+
@surma
|
|
64
|
+
|
|
65
|
+
@Paul_Kinlan
|
|
66
|
+
|
|
67
|
+
@paul_irish
|
|
68
|
+
|
|
69
|
+
@aerotwist
|
|
70
|
+
|
|
71
|
+
@jason_mayes
|
|
72
|
+
|
|
73
|
+
@sundarpichai
|
|
74
|
+
|
|
75
|
+
@ThomasOrTK
|
|
76
|
+
|
|
77
|
+
@GrannisWill
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"vanila-javascript"
|
|
13
13
|
],
|
|
14
14
|
"homepage": "https://webqit.io/tooling/webflo",
|
|
15
|
-
"version": "0.10.
|
|
15
|
+
"version": "0.10.4",
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@octokit/webhooks": "^7.15.1",
|
|
39
|
-
"@webqit/backpack": "^0.0
|
|
39
|
+
"@webqit/backpack": "^0.1.0",
|
|
40
40
|
"@webqit/oohtml-ssr": "^1.0.3",
|
|
41
41
|
"@webqit/util": "^0.8.9",
|
|
42
42
|
"client-sessions": "^0.8.0",
|
package/src/Context.js
CHANGED
|
@@ -21,6 +21,10 @@ export default class Context {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
get name() {
|
|
25
|
+
return 'webflo';
|
|
26
|
+
}
|
|
27
|
+
|
|
24
28
|
// create
|
|
25
29
|
static create(...args) {
|
|
26
30
|
return new this(...args);
|
|
@@ -31,9 +35,9 @@ export default class Context {
|
|
|
31
35
|
return this.dict.CWD || '';
|
|
32
36
|
}
|
|
33
37
|
|
|
34
|
-
//
|
|
35
|
-
get
|
|
36
|
-
return this.dict.
|
|
38
|
+
// meta
|
|
39
|
+
get meta() {
|
|
40
|
+
return this.dict.meta || {};
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
// app
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* imports
|
|
4
4
|
*/
|
|
5
5
|
import { _merge } from '@webqit/util/obj/index.js';
|
|
6
|
-
import
|
|
6
|
+
import { Dotfile } from '@webqit/backpack';
|
|
7
7
|
|
|
8
|
-
export default class Env extends
|
|
8
|
+
export default class Env extends Dotfile {
|
|
9
9
|
|
|
10
10
|
// Base name
|
|
11
11
|
get name() {
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* imports
|
|
4
4
|
*/
|
|
5
5
|
import { _merge } from '@webqit/util/obj/index.js';
|
|
6
|
-
import
|
|
6
|
+
import { Dotfile } from '@webqit/backpack';
|
|
7
7
|
|
|
8
|
-
export default class Layout extends
|
|
8
|
+
export default class Layout extends Dotfile {
|
|
9
9
|
|
|
10
10
|
// Base name
|
|
11
11
|
get name() {
|
|
@@ -6,9 +6,9 @@ import Url from 'url';
|
|
|
6
6
|
import { _merge } from '@webqit/util/obj/index.js';
|
|
7
7
|
import { _before } from '@webqit/util/str/index.js';
|
|
8
8
|
import { _isObject, _isTypeObject } from '@webqit/util/js/index.js';
|
|
9
|
-
import
|
|
9
|
+
import { Dotfile } from '@webqit/backpack';
|
|
10
10
|
|
|
11
|
-
export default class Origins extends
|
|
11
|
+
export default class Origins extends Dotfile {
|
|
12
12
|
|
|
13
13
|
// Base name
|
|
14
14
|
get name() {
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { _merge } from '@webqit/util/obj/index.js';
|
|
6
6
|
import { _isObject } from '@webqit/util/js/index.js';
|
|
7
|
-
import
|
|
7
|
+
import { Dotfile } from '@webqit/backpack';
|
|
8
8
|
|
|
9
|
-
export default class Virtualization extends
|
|
9
|
+
export default class Virtualization extends Dotfile {
|
|
10
10
|
|
|
11
11
|
// Base name
|
|
12
12
|
get name() {
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
import { _merge } from '@webqit/util/obj/index.js';
|
|
6
6
|
import { _isNumeric } from '@webqit/util/js/index.js';
|
|
7
7
|
import { _before, _after } from '@webqit/util/str/index.js';
|
|
8
|
-
import
|
|
8
|
+
import { Dotfile } from '@webqit/backpack';
|
|
9
9
|
|
|
10
|
-
export default class Client extends
|
|
10
|
+
export default class Client extends Dotfile {
|
|
11
11
|
|
|
12
12
|
// Base name
|
|
13
13
|
get name() {
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* imports
|
|
4
4
|
*/
|
|
5
5
|
import { _merge } from '@webqit/util/obj/index.js';
|
|
6
|
-
import
|
|
6
|
+
import { Dotfile } from '@webqit/backpack';
|
|
7
7
|
|
|
8
|
-
export default class Server extends
|
|
8
|
+
export default class Server extends Dotfile {
|
|
9
9
|
|
|
10
10
|
// Base name
|
|
11
11
|
get name() {
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
import { _merge } from '@webqit/util/obj/index.js';
|
|
6
6
|
import { _isNumeric } from '@webqit/util/js/index.js';
|
|
7
7
|
import { _before, _after } from '@webqit/util/str/index.js';
|
|
8
|
-
import
|
|
8
|
+
import { Dotfile } from '@webqit/backpack';
|
|
9
9
|
|
|
10
|
-
export default class Worker extends
|
|
10
|
+
export default class Worker extends Dotfile {
|
|
11
11
|
|
|
12
12
|
// Base name
|
|
13
13
|
get name() {
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
import Url from 'url';
|
|
6
6
|
import { _merge } from '@webqit/util/obj/index.js';
|
|
7
7
|
import { _isObject } from '@webqit/util/js/index.js';
|
|
8
|
-
import
|
|
8
|
+
import { Dotfile } from '@webqit/backpack';
|
|
9
9
|
|
|
10
|
-
export default class Headers extends
|
|
10
|
+
export default class Headers extends Dotfile {
|
|
11
11
|
|
|
12
12
|
// Base name
|
|
13
13
|
get name() {
|
|
@@ -6,9 +6,9 @@ import Url from 'url';
|
|
|
6
6
|
import { _merge } from '@webqit/util/obj/index.js';
|
|
7
7
|
import { _after } from '@webqit/util/str/index.js';
|
|
8
8
|
import { _isObject, _isNumeric } from '@webqit/util/js/index.js';
|
|
9
|
-
import
|
|
9
|
+
import { Dotfile } from '@webqit/backpack';
|
|
10
10
|
|
|
11
|
-
export default class Redirects extends
|
|
11
|
+
export default class Redirects extends Dotfile {
|
|
12
12
|
|
|
13
13
|
// Base name
|
|
14
14
|
get name() {
|
|
@@ -8,9 +8,9 @@ import { _merge } from '@webqit/util/obj/index.js';
|
|
|
8
8
|
import { _isNumeric } from '@webqit/util/js/index.js';
|
|
9
9
|
import { _before, _after } from '@webqit/util/str/index.js';
|
|
10
10
|
import { initialGetIndex } from '@webqit/backpack/src/cli/Promptx.js';
|
|
11
|
-
import
|
|
11
|
+
import { Dotfile } from '@webqit/backpack';
|
|
12
12
|
|
|
13
|
-
export default class Manifest extends
|
|
13
|
+
export default class Manifest extends Dotfile {
|
|
14
14
|
|
|
15
15
|
// Base name
|
|
16
16
|
get name() {
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { _merge } from '@webqit/util/obj/index.js';
|
|
6
6
|
import { _isObject } from '@webqit/util/js/index.js';
|
|
7
|
-
import
|
|
7
|
+
import { Dotfile } from '@webqit/backpack';
|
|
8
8
|
|
|
9
|
-
export default class Ssg extends
|
|
9
|
+
export default class Ssg extends Dotfile {
|
|
10
10
|
|
|
11
11
|
// Base name
|
|
12
12
|
get name() {
|
|
@@ -88,7 +88,7 @@ export default class Runtime {
|
|
|
88
88
|
// Needed to allow window.document.location
|
|
89
89
|
// to update to window.location
|
|
90
90
|
window.setTimeout(() => {
|
|
91
|
-
this.go(Url.copy(window.document.location), { src: window.document.location, srcType: 'history', });
|
|
91
|
+
this.go(Url.copy(window.document.location), {}, { src: window.document.location, srcType: 'history', });
|
|
92
92
|
}, 0);
|
|
93
93
|
});
|
|
94
94
|
|
|
@@ -7,7 +7,7 @@ import Url from 'url';
|
|
|
7
7
|
import Path from 'path';
|
|
8
8
|
import { _beforeLast } from '@webqit/util/str/index.js';
|
|
9
9
|
import { _isObject, _isArray } from '@webqit/util/js/index.js';
|
|
10
|
-
import
|
|
10
|
+
import { jsFile } from '@webqit/backpack/src/dotfile/index.js';
|
|
11
11
|
import { gzipSync, brotliCompressSync } from 'zlib';
|
|
12
12
|
import EsBuild from 'esbuild';
|
|
13
13
|
|
|
@@ -197,11 +197,11 @@ async function bundle(gen, outfile, asModule = false) {
|
|
|
197
197
|
if (cx.logger) {
|
|
198
198
|
let waiting = cx.logger.waiting(cx.logger.f`Writing the ES module file: ${moduleFile}`);
|
|
199
199
|
waiting.start();
|
|
200
|
-
|
|
200
|
+
jsFile.write(gen, moduleFile, 'ES Module file');
|
|
201
201
|
waiting.stop();
|
|
202
202
|
cx.logger.info(cx.logger.f`The module file: ${moduleFile}`);
|
|
203
203
|
} else {
|
|
204
|
-
|
|
204
|
+
jsFile.write(gen, moduleFile, 'ES Module file');
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
// ----------------
|
|
@@ -72,14 +72,25 @@ export default class Worker {
|
|
|
72
72
|
|
|
73
73
|
// -------------
|
|
74
74
|
// ONFETCH
|
|
75
|
-
self.addEventListener('fetch',
|
|
75
|
+
self.addEventListener('fetch', event => {
|
|
76
76
|
// URL schemes that might arrive here but not supported; e.g.: chrome-extension://
|
|
77
|
-
if (!
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
if (!event.request.url.startsWith('http')) return;
|
|
78
|
+
event.respondWith((async (req, evt) => {
|
|
79
|
+
const requestInit = [
|
|
80
|
+
'method', 'headers', 'mode', 'credentials', 'cache', 'redirect', 'referrer', 'integrity',
|
|
81
|
+
].reduce((init, prop) => ({ [prop]: req[prop], ...init }), {});
|
|
82
|
+
if (!['GET', 'HEAD'].includes(req.method)) {
|
|
83
|
+
requestInit.body = await req.text();
|
|
84
|
+
}
|
|
85
|
+
// Now, the following is key:
|
|
86
|
+
// The browser likes to use "force-cache" for "navigate" requests, when, e.g: re-entering your site with the back button
|
|
87
|
+
// Problem here, force-cache forces out JSON not HTML as per webflo's design.
|
|
88
|
+
// So, we detect this scenerio and avoid it.
|
|
89
|
+
if (req.cache === 'force-cache'/* && req.mode === 'navigate' - even webflo client init call also comes with that... needs investigation */) {
|
|
90
|
+
requestInit.cache = 'default';
|
|
91
|
+
}
|
|
92
|
+
return this.go(req.url, requestInit, { event: evt });
|
|
93
|
+
})(event.request, event));
|
|
83
94
|
});
|
|
84
95
|
|
|
85
96
|
// ---------------
|
|
@@ -107,16 +118,15 @@ export default class Worker {
|
|
|
107
118
|
init = { referrer: this.location.href, ...init };
|
|
108
119
|
// ------------
|
|
109
120
|
// The request object
|
|
110
|
-
let request = this.generateRequest(url.href, init);
|
|
111
|
-
if (detail.event
|
|
112
|
-
request = detail.event.request;
|
|
121
|
+
let request = await this.generateRequest(url.href, init);
|
|
122
|
+
if (detail.event) {
|
|
113
123
|
Object.defineProperty(detail.event, 'request', { value: request });
|
|
114
124
|
}
|
|
115
125
|
// The navigation event
|
|
116
126
|
let httpEvent = new HttpEvent(request, detail, (id = null, persistent = false) => this.getSession(httpEvent, id, persistent));
|
|
117
127
|
httpEvent.port.listen(message => {
|
|
118
128
|
if (message.$type === 'handler:hints' && message.session) {
|
|
119
|
-
// TODO: Sync
|
|
129
|
+
// TODO: Sync session data from client
|
|
120
130
|
return Promise.resolve();
|
|
121
131
|
}
|
|
122
132
|
});
|
|
@@ -134,15 +144,7 @@ export default class Worker {
|
|
|
134
144
|
|
|
135
145
|
// Generates request object
|
|
136
146
|
generateRequest(href, init) {
|
|
137
|
-
|
|
138
|
-
// The browser likes to use "force-cache" for "navigate" requests
|
|
139
|
-
// when, for example, the back button was used.
|
|
140
|
-
// Thus the origin server would still not be contacted by the self.fetch() below, leading to inconsistencies in responses.
|
|
141
|
-
// So, we detect this scenerio and avoid it.
|
|
142
|
-
if (init.mode === 'navigate' && init.cache === 'force-cache') {
|
|
143
|
-
init = { ...init, cache: 'default' };
|
|
144
|
-
}
|
|
145
|
-
let request = new Request(href, init);
|
|
147
|
+
let request = new Request(href, init);
|
|
146
148
|
return request;
|
|
147
149
|
}
|
|
148
150
|
|
|
@@ -94,7 +94,7 @@ const xHttpMessage = (whatwagHttpMessage, Headers, FormData) => {
|
|
|
94
94
|
this.bodyAttrs.jsonfied = new Promise(async (resolve, reject) => {
|
|
95
95
|
var messageInstance = this, jsonfied, contentType = messageInstance.headers.get('content-type') || '';
|
|
96
96
|
var type = contentType === 'application/json' || this.bodyAttrs.json ? 'json' : (
|
|
97
|
-
contentType === 'application/x-www-form-urlencoded' || contentType.startsWith('multipart/') || this.bodyAttrs.formData ? 'formData' : (
|
|
97
|
+
contentType === 'application/x-www-form-urlencoded' || contentType.startsWith('multipart/form-data') || this.bodyAttrs.formData ? 'formData' : (
|
|
98
98
|
contentType === 'text/plain' ? 'plain' : 'other'
|
|
99
99
|
)
|
|
100
100
|
);
|
|
@@ -62,6 +62,13 @@ const xRequest = (whatwagRequest, Headers, FormData, Blob) => class extends xHtt
|
|
|
62
62
|
return 'referrer' in this.attrs ? this.attrs.referrer : super.referrer;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
static compat(request, url = null) {
|
|
66
|
+
if (request instanceof whatwagRequest) {
|
|
67
|
+
return Object.setPrototypeOf(request, new this);
|
|
68
|
+
}
|
|
69
|
+
return new this(url, request);
|
|
70
|
+
}
|
|
71
|
+
|
|
65
72
|
};
|
|
66
73
|
|
|
67
74
|
export default xRequest;
|
package/src/webflo.js
CHANGED
|
@@ -5,23 +5,21 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import Url from 'url';
|
|
7
7
|
import Path from 'path';
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
8
|
+
import { jsonFile } from '@webqit/backpack/src/dotfile/index.js';
|
|
9
|
+
import { Logger, Cli } from '@webqit/backpack';
|
|
10
10
|
import * as WebfloPI from './index.js';
|
|
11
|
-
import Context from './Context.js';
|
|
12
|
-
import Cli from './Cli.js';
|
|
13
11
|
|
|
14
12
|
const dirSelf = Path.dirname(Url.fileURLToPath(import.meta.url));
|
|
15
|
-
const webfloJson =
|
|
16
|
-
const appJson =
|
|
13
|
+
const webfloJson = jsonFile.read(Path.join(dirSelf, '../package.json'));
|
|
14
|
+
const appJson = jsonFile.read('./package.json');
|
|
17
15
|
|
|
18
16
|
/**
|
|
19
17
|
* @cx
|
|
20
18
|
*/
|
|
21
|
-
const cx = Context.create({
|
|
22
|
-
|
|
19
|
+
const cx = WebfloPI.Context.create({
|
|
20
|
+
meta: { title: webfloJson.title, version: webfloJson.version },
|
|
23
21
|
app: { title: appJson.title, version: appJson.version },
|
|
24
|
-
logger,
|
|
22
|
+
logger: Logger,
|
|
25
23
|
config: WebfloPI.config,
|
|
26
24
|
middlewares: [ WebfloPI.deployment.origins.webhook, ],
|
|
27
25
|
});
|
package/src/Cli.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @imports
|
|
5
|
-
*/
|
|
6
|
-
import { _toTitle } from '@webqit/util/str/index.js';
|
|
7
|
-
import { _merge, _set, _get } from '@webqit/util/obj/index.js';
|
|
8
|
-
import { _isClass, _isFunction, _isObject, _isEmpty, _isString } from '@webqit/util/js/index.js';
|
|
9
|
-
import { Promptx } from '@webqit/backpack/src/cli/Promptx.js';
|
|
10
|
-
import parseArgs from '@webqit/backpack/src/cli/parseArgs.js';
|
|
11
|
-
|
|
12
|
-
export default class Cli {
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @constructor
|
|
16
|
-
*
|
|
17
|
-
* @param Object api
|
|
18
|
-
*/
|
|
19
|
-
constructor(api) {
|
|
20
|
-
this.api = api;
|
|
21
|
-
this.nsSeparator = '::';
|
|
22
|
-
// Generate available options
|
|
23
|
-
this.availableConfigs = {};
|
|
24
|
-
this.availableCommands = {};
|
|
25
|
-
const discoverConfigs = (namespace, piObj) => Object.keys(piObj).forEach(name => {
|
|
26
|
-
let pathname = `${name}${this.nsSeparator}${namespace}`.toLowerCase();
|
|
27
|
-
if (_isClass(piObj[name])) {
|
|
28
|
-
if (piObj[name]['@desc']) this.availableConfigs[pathname] = piObj[name]['@desc'];
|
|
29
|
-
} else if (_isObject(piObj[name])) discoverConfigs(pathname, piObj[name]);
|
|
30
|
-
});
|
|
31
|
-
const discoverCommands = (namespace, piObj) => Object.keys(piObj).forEach(name => {
|
|
32
|
-
let pathname = `${name}${this.nsSeparator}${namespace}`.toLowerCase();
|
|
33
|
-
if (!_isClass(piObj[name]) && _isFunction(piObj[name])) {
|
|
34
|
-
if (!piObj[name]['@desc']) this.availableCommands[pathname] = piObj[name]['@desc'];
|
|
35
|
-
} else if (_isObject(piObj[name])) discoverCommands(pathname, piObj[name]);
|
|
36
|
-
});
|
|
37
|
-
Object.keys(this.api).forEach(name => {
|
|
38
|
-
if (name === 'config') discoverConfigs(name, this.api[name]);
|
|
39
|
-
else discoverCommands(name, this.api[name]);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @exec
|
|
45
|
-
*/
|
|
46
|
-
async exec(cx) {
|
|
47
|
-
const { command, keywords, flags, options, ellipsis } = parseArgs(process.argv);
|
|
48
|
-
cx.flags = flags;
|
|
49
|
-
// ------------
|
|
50
|
-
if (cx.webflo.version) {
|
|
51
|
-
cx.logger.log('');
|
|
52
|
-
cx.logger.banner(cx.webflo.title, cx.webflo.version || '');
|
|
53
|
-
cx.logger.log('');
|
|
54
|
-
}
|
|
55
|
-
// ------------
|
|
56
|
-
if (command === 'help') {
|
|
57
|
-
cx.logger.title(`> COMMAND LINE HELP`);
|
|
58
|
-
cx.logger.log('');
|
|
59
|
-
// ------------
|
|
60
|
-
cx.logger.log(cx.logger.f`Say "webflo <${'command'}>"`);
|
|
61
|
-
cx.logger.log(cx.logger.f`Where <${'command'}> is one of:`);
|
|
62
|
-
cx.logger.log(cx.logger.f`${this.availableCommands}`);
|
|
63
|
-
cx.logger.log('');
|
|
64
|
-
// ------------
|
|
65
|
-
cx.logger.log(cx.logger.f`Or say "webflo config", or "webflo config <${'path'}>"`);
|
|
66
|
-
cx.logger.log(cx.logger.f`Where <${'path'}> is one of:`);
|
|
67
|
-
cx.logger.log(cx.logger.f`${this.availableConfigs}`);
|
|
68
|
-
cx.logger.log('');
|
|
69
|
-
// ------------
|
|
70
|
-
cx.logger.log(cx.logger.f`You may also refer to the Webflo DOCS as ${'https://webqit.io/tooling/webflo'}`);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
// ------------
|
|
74
|
-
const keywordList = Object.keys(keywords);
|
|
75
|
-
const fcn = keywordList[0];
|
|
76
|
-
const resolveIdentifier = (fcn, isConfig) => {
|
|
77
|
-
let namespaceObj = isConfig ? this.availableConfigs : this.availableCommands;
|
|
78
|
-
let matches = Object.keys(namespaceObj).filter(path => `${path}${this.nsSeparator}`.startsWith(`${fcn}${this.nsSeparator}`));
|
|
79
|
-
if (matches.length === 1) {
|
|
80
|
-
return matches[0];
|
|
81
|
-
}
|
|
82
|
-
return matches;
|
|
83
|
-
};
|
|
84
|
-
const pathNisplayName = path => path.split(this.nsSeparator).slice(0, -1).join(this.nsSeparator);
|
|
85
|
-
const promptIdentifier = async (preselection, isConfig) => {
|
|
86
|
-
let namespaceObj = isConfig ? this.availableConfigs : this.availableCommands;
|
|
87
|
-
let selection = await Promptx({
|
|
88
|
-
name: 'fcn',
|
|
89
|
-
type: 'select',
|
|
90
|
-
choices: (!_isEmpty(preselection) ? preselection : Object.keys(namespaceObj)).map(path => ({ value: path, title: pathNisplayName(path) })).concat({ value: '<' }),
|
|
91
|
-
message: 'Please select a function to continue, or "<" to exit',
|
|
92
|
-
}).then(d => d.fcn);
|
|
93
|
-
if (selection === '<') process.exit();
|
|
94
|
-
return selection;
|
|
95
|
-
};
|
|
96
|
-
// ------------
|
|
97
|
-
let isConfig = command === 'config', _fcn = isConfig ? fcn : command, resolvedFcn;
|
|
98
|
-
if (!(_fcn && _isString(resolvedFcn = resolveIdentifier(_fcn, isConfig))) || ellipsis) {
|
|
99
|
-
cx.logger.title(`> webflo ${isConfig ? 'config ' : ''}${_fcn || ''}...`);
|
|
100
|
-
cx.logger.log('');
|
|
101
|
-
resolvedFcn = await promptIdentifier(resolvedFcn, isConfig);
|
|
102
|
-
}
|
|
103
|
-
cx.logger.title(`> webflo ${isConfig ? 'config ' : ''}${pathNisplayName(resolvedFcn)}`);
|
|
104
|
-
cx.logger.log('');
|
|
105
|
-
// ------------
|
|
106
|
-
// Process command
|
|
107
|
-
if (isConfig) {
|
|
108
|
-
const configClass = _get(this.api, _toTitle(resolvedFcn).split(this.nsSeparator).reverse());
|
|
109
|
-
const configurator = new configClass(cx);
|
|
110
|
-
const config = await configurator.read();
|
|
111
|
-
const givenOptionsList = Object.keys(options);
|
|
112
|
-
if (givenOptionsList.length) {
|
|
113
|
-
const optionsStructured = {};
|
|
114
|
-
givenOptionsList.forEach(path => {
|
|
115
|
-
_set(optionsStructured, path.split('.'), options[path]);
|
|
116
|
-
});
|
|
117
|
-
await configurator.write(_merge(true, config, optionsStructured));
|
|
118
|
-
} else {
|
|
119
|
-
await Promptx(configurator.questions(config)).then(async _config => {
|
|
120
|
-
await configurator.write(_merge(true, config, _config));
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
} else {
|
|
124
|
-
const func = _get(this.api, resolvedFcn.split(this.nsSeparator).reverse());
|
|
125
|
-
await func.call(cx, ...keywordList);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
cx.logger.log('');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
}
|
package/src/Configurator.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @imports
|
|
4
|
-
*/
|
|
5
|
-
import Path from 'path';
|
|
6
|
-
import { _merge } from '@webqit/util/obj/index.js';
|
|
7
|
-
import { initialGetIndex } from '@webqit/backpack/src/cli/Promptx.js';
|
|
8
|
-
import { DotJson, DotEnv, anyExists } from '@webqit/backpack/src/dotfiles/index.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @exports
|
|
12
|
-
*/
|
|
13
|
-
export default class Configurator {
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* The default initializer.
|
|
17
|
-
*
|
|
18
|
-
* @param Context cx
|
|
19
|
-
*/
|
|
20
|
-
constructor(cx) {
|
|
21
|
-
this.cx = cx;
|
|
22
|
-
this.givenExt = this.cx.flags.mode ? `.${this.cx.flags.mode}` : '';
|
|
23
|
-
this.availableExt = anyExists([ this.givenExt, '', '.example' ], ext => this.resolveFileName(ext));
|
|
24
|
-
if (this.isEnv) {
|
|
25
|
-
this.availableEnvExt = anyExists([ this.givenExt, '', '.example' ], ext => this.resolveEnvFileName(ext));
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// ------------
|
|
30
|
-
|
|
31
|
-
get configDir() {
|
|
32
|
-
return Path.join(this.cx.CWD || ``, `./.webqit/webflo/config/`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
get envDir() {
|
|
36
|
-
return Path.resolve(this.cx.CWD || '');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// ------------
|
|
40
|
-
|
|
41
|
-
static read(...args) {
|
|
42
|
-
let instance = new this(...args);
|
|
43
|
-
return instance.read();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
static write(config, ...args) {
|
|
48
|
-
let instance = new this(...args);
|
|
49
|
-
return instance.write(config);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// ------------
|
|
53
|
-
|
|
54
|
-
async read() {
|
|
55
|
-
let config = DotJson.read(this.resolveFileName(this.availableExt));
|
|
56
|
-
if (this.isEnv) {
|
|
57
|
-
let config2 = { entries: DotEnv.read(this.resolveEnvFileName(this.availableEnvExt)) || {}, };
|
|
58
|
-
// The rewrite below is because entries should not also appear in json
|
|
59
|
-
//config.entries = _merge(config.entries || {}, config2.entries);
|
|
60
|
-
config = _merge(config, config2);
|
|
61
|
-
}
|
|
62
|
-
return this.withDefaults(config);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async write(config) {
|
|
66
|
-
if (this.isEnv) {
|
|
67
|
-
config = { ...config };
|
|
68
|
-
DotEnv.write(config.entries, this.resolveEnvFileName(this.givenExt));
|
|
69
|
-
// The delete below is because entries should not also appear in json
|
|
70
|
-
delete config.entries;
|
|
71
|
-
}
|
|
72
|
-
DotJson.write(config, this.resolveFileName(this.givenExt));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
questions() {
|
|
76
|
-
return [];
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// ------------
|
|
80
|
-
|
|
81
|
-
resolveFileName(ext) {
|
|
82
|
-
return `${this.configDir}/${this.name}${ext}.json`;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
resolveEnvFileName(ext) {
|
|
86
|
-
return `${this.envDir}/.${this.name}${ext}`;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
withDefaults(config) {
|
|
90
|
-
return config;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
indexOfInitial(options, initial) {
|
|
94
|
-
return initialGetIndex(options, initial);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
}
|