@iebh/tera-fy 1.0.5 → 1.0.6
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 +25 -1
- package/lib/terafy.client.js +64 -37
- package/lib/terafy.server.js +33 -14
- package/package.json +2 -2
- package/plugins/vue.js +9 -4
package/README.md
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
TERA-fy
|
|
2
2
|
=======
|
|
3
|
-
TERA website worker.
|
|
3
|
+
TERA website worker, intended to be embedded with TERA tools.
|
|
4
4
|
|
|
5
5
|
* [API workbench](https://iebh.github.io/TERA-fy/)
|
|
6
6
|
* [TERA-fy Class API](./api.md)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
TERA-fy is a component intended to be dropped into a sub-site / tool used with in the main [TERA](https://tera-tools.com) project. It provides various functionality like data sync with the parent TERA instance.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Quick Start
|
|
13
|
+
-----------
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import TeraFy from '@iebh/tera-fy';
|
|
17
|
+
import TerafyVue from '@iebh/tera-fy/plugins/vue';
|
|
18
|
+
let terafy = new TeraFy()
|
|
19
|
+
.set('devMode', true) // Set this option to see debugging messages
|
|
20
|
+
.use(TerafyVue); // Add the Vue plugin
|
|
21
|
+
|
|
22
|
+
// Initialize everything
|
|
23
|
+
await terafy.init();
|
|
24
|
+
|
|
25
|
+
// Require that the active session has a project selected
|
|
26
|
+
await terafy.requireProject();
|
|
27
|
+
|
|
28
|
+
// Go fetch the state of the active project
|
|
29
|
+
let projectState = await terafy.getProjectState(); //= Object representing the active project
|
|
30
|
+
```
|
package/lib/terafy.client.js
CHANGED
|
@@ -105,14 +105,19 @@ export default class TeraFy {
|
|
|
105
105
|
* @param {Object} message Message object to send
|
|
106
106
|
*/
|
|
107
107
|
sendRaw(message) {
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
let payload;
|
|
109
|
+
try {
|
|
110
|
+
payload = {
|
|
110
111
|
TERA: 1,
|
|
111
112
|
id: message.id || nanoid(),
|
|
112
113
|
...cloneDeep(message), // Need to clone to resolve promise nasties
|
|
113
|
-
}
|
|
114
|
-
this.settings.restrictOrigin
|
|
115
|
-
)
|
|
114
|
+
};
|
|
115
|
+
this.dom.iframe.contentWindow.postMessage(payload, this.settings.restrictOrigin);
|
|
116
|
+
} catch (e) {
|
|
117
|
+
this.debug('ERROR', 'Message compose client->server:', e);
|
|
118
|
+
this.debug('ERROR', 'Attempted to dispatch payload client->server', payload);
|
|
119
|
+
throw e;
|
|
120
|
+
}
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
|
|
@@ -181,7 +186,7 @@ export default class TeraFy {
|
|
|
181
186
|
|
|
182
187
|
// }}}
|
|
183
188
|
|
|
184
|
-
// Init - constructor(),
|
|
189
|
+
// Init - constructor(), init(), inject*() {{{
|
|
185
190
|
|
|
186
191
|
/**
|
|
187
192
|
* Setup the TERA-fy client singleton
|
|
@@ -193,42 +198,34 @@ export default class TeraFy {
|
|
|
193
198
|
}
|
|
194
199
|
|
|
195
200
|
|
|
196
|
-
/**
|
|
197
|
-
* Set or toggle devMode
|
|
198
|
-
*
|
|
199
|
-
* @param {String|Boolean} [devModeEnabled='toggle'] Optional boolean to force dev mode
|
|
200
|
-
*
|
|
201
|
-
* @returns {TeraFy} This chainable terafy instance
|
|
202
|
-
*/
|
|
203
|
-
toggleDevMode(devModeEnabled = 'toggle') {
|
|
204
|
-
this.settings.devMode = devModeEnabled === 'toggle'
|
|
205
|
-
? !this.settings.devMode
|
|
206
|
-
: devModeEnabled;
|
|
207
|
-
|
|
208
|
-
this.dom.el.classList.toggle('dev-mode', this.settings.devMode);
|
|
209
|
-
return this;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
201
|
/**
|
|
214
202
|
* Initalize the TERA client singleton
|
|
203
|
+
*
|
|
204
|
+
* @returns {Promise<TeraFy>} An eventual promise which will resovle with this terafy instance
|
|
215
205
|
*/
|
|
216
206
|
init() {
|
|
217
207
|
window.addEventListener('message', this.acceptMessage.bind(this));
|
|
218
208
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
.
|
|
224
|
-
|
|
209
|
+
return Promise.all([
|
|
210
|
+
// Init core functions async
|
|
211
|
+
this.injectComms(),
|
|
212
|
+
this.injectStylesheet(),
|
|
213
|
+
this.injectMethods(),
|
|
214
|
+
|
|
215
|
+
// Init all plugins
|
|
216
|
+
...this.plugins
|
|
217
|
+
.map(plugin => plugin.init()),
|
|
218
|
+
])
|
|
219
|
+
.then(()=> this)
|
|
225
220
|
}
|
|
226
221
|
|
|
227
222
|
|
|
228
223
|
/**
|
|
229
224
|
* Find an existing active TERA server OR initalize one
|
|
225
|
+
*
|
|
226
|
+
* @returns {Promise} A promise which will resolve when the loading has completed and we have found a parent TERA instance or initiallized a child
|
|
230
227
|
*/
|
|
231
|
-
|
|
228
|
+
injectComms() { return new Promise(resolve => {
|
|
232
229
|
this.dom.el = document.createElement('div')
|
|
233
230
|
this.dom.el.id = 'tera-fy';
|
|
234
231
|
this.dom.el.classList.toggle('dev-mode', this.settings.devMode);
|
|
@@ -240,12 +237,13 @@ export default class TeraFy {
|
|
|
240
237
|
this.dom.iframe.setAttribute('sandbox', 'allow-downloads allow-scripts allow-same-origin');
|
|
241
238
|
this.dom.iframe.addEventListener('load', ()=> {
|
|
242
239
|
this.debug('TERA EMBED FRAME READY');
|
|
240
|
+
resolve();
|
|
243
241
|
});
|
|
244
242
|
|
|
245
243
|
// Start document load sequence + append to DOM
|
|
246
244
|
this.dom.iframe.src = this.settings.siteUrl;
|
|
247
245
|
this.dom.el.append(this.dom.iframe);
|
|
248
|
-
}
|
|
246
|
+
})}
|
|
249
247
|
|
|
250
248
|
|
|
251
249
|
/**
|
|
@@ -306,20 +304,33 @@ export default class TeraFy {
|
|
|
306
304
|
this.methods.forEach(method =>
|
|
307
305
|
this[method] = this.rpc.bind(this, method)
|
|
308
306
|
);
|
|
307
|
+
this.debug('Remote methods installed:', this.methods);
|
|
309
308
|
}
|
|
310
309
|
// }}}
|
|
311
310
|
|
|
312
|
-
// Utility - debug(), use(), mixin(),
|
|
311
|
+
// Utility - debug(), use(), mixin(), toggleDevMode(), toggleFocus() {{{
|
|
313
312
|
|
|
314
313
|
/**
|
|
315
314
|
* Debugging output function
|
|
316
315
|
* This function will only act if `settings.devMode` is truthy
|
|
317
316
|
*
|
|
317
|
+
* @param {'INFO'|'LOG'|'WARN'|'ERROR'} [status] Optional prefixing level to mark the message as. 'WARN' and 'ERROR' will always show reguardless of devMode being enabled
|
|
318
318
|
* @param {String} [msg...] Output to show
|
|
319
319
|
*/
|
|
320
320
|
debug(...msg) {
|
|
321
|
-
|
|
322
|
-
|
|
321
|
+
let method = 'log';
|
|
322
|
+
// Argument mangling for prefixing method {{{
|
|
323
|
+
if (typeof msg[0] == 'string' && ['INFO', 'LOG', 'WARN', 'ERROR'].includes(msg[0])) {
|
|
324
|
+
method = msg.shift().toLowerCase();
|
|
325
|
+
}
|
|
326
|
+
// }}}
|
|
327
|
+
|
|
328
|
+
if (
|
|
329
|
+
['INFO', 'LOG'].includes(method)
|
|
330
|
+
&& !this.settings.devMode
|
|
331
|
+
) return;
|
|
332
|
+
|
|
333
|
+
console[method](
|
|
323
334
|
'%c[TERA-FY CLIENT]',
|
|
324
335
|
'font-weight: bold; color: #ff5722;',
|
|
325
336
|
...msg,
|
|
@@ -389,18 +400,34 @@ export default class TeraFy {
|
|
|
389
400
|
}
|
|
390
401
|
|
|
391
402
|
|
|
403
|
+
/**
|
|
404
|
+
* Set or toggle devMode
|
|
405
|
+
*
|
|
406
|
+
* @param {String|Boolean} [devModeEnabled='toggle'] Optional boolean to force dev mode
|
|
407
|
+
*
|
|
408
|
+
* @returns {TeraFy} This chainable terafy instance
|
|
409
|
+
*/
|
|
410
|
+
toggleDevMode(devModeEnabled = 'toggle') {
|
|
411
|
+
this.settings.devMode = devModeEnabled === 'toggle'
|
|
412
|
+
? !this.settings.devMode
|
|
413
|
+
: devModeEnabled;
|
|
414
|
+
|
|
415
|
+
if (this.dom.el) // Have we actually set up yet?
|
|
416
|
+
this.dom.el.classList.toggle('dev-mode', this.settings.devMode);
|
|
417
|
+
|
|
418
|
+
return this;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
|
|
392
422
|
/**
|
|
393
423
|
* Fit the nested TERA server to a full-screen
|
|
394
424
|
* This is usually because the server component wants to perform some user activity like calling $prompt
|
|
395
425
|
*
|
|
396
426
|
* @param {String|Boolean} [isFocused='toggle'] Whether to fullscreen the embedded component
|
|
397
|
-
*
|
|
398
|
-
* @returns {TeraFy} This chainable terafy instance
|
|
399
427
|
*/
|
|
400
428
|
toggleFocus(isFocused = 'toggle') {
|
|
401
429
|
this.debug('Request focus', {isFocused});
|
|
402
430
|
globalThis.document.body.classList.toggle('tera-fy-focus', isFocused === 'toggle' ? undefined : isFocused);
|
|
403
|
-
return this;
|
|
404
431
|
}
|
|
405
432
|
// }}}
|
|
406
433
|
}
|
package/lib/terafy.server.js
CHANGED
|
@@ -31,18 +31,22 @@ export default class TeraFyServer {
|
|
|
31
31
|
* @returns {Object} A context, which is this instance extended with additional properties
|
|
32
32
|
*/
|
|
33
33
|
createContext(e) {
|
|
34
|
-
// Rather ugly shallow-copy-of
|
|
34
|
+
// Rather ugly shallow-copy-of instancr hack from https://stackoverflow.com/a/44782052/1295040
|
|
35
35
|
return Object.assign(Object.create(Object.getPrototypeOf(this)), this, {
|
|
36
36
|
messageEvent: e,
|
|
37
37
|
sendRaw(message) { // Override sendRaw because we can't do this inline for security reasons
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{
|
|
38
|
+
let payload;
|
|
39
|
+
try {
|
|
40
|
+
payload = {
|
|
41
41
|
TERA: 1,
|
|
42
42
|
...cloneDeep(message), // Need to clone to resolve promise nasties
|
|
43
|
-
}
|
|
44
|
-
this.settings.restrictOrigin
|
|
45
|
-
)
|
|
43
|
+
};
|
|
44
|
+
e.source.postMessage(payload, this.settings.restrictOrigin);
|
|
45
|
+
} catch (e) {
|
|
46
|
+
this.debug('ERROR', 'Message compose/reply via server->cient:', e);
|
|
47
|
+
this.debug('ERROR', 'Attempted to dispatch payload server(via reply)->client', payload);
|
|
48
|
+
throw e;
|
|
49
|
+
}
|
|
46
50
|
},
|
|
47
51
|
});
|
|
48
52
|
}
|
|
@@ -124,14 +128,18 @@ export default class TeraFyServer {
|
|
|
124
128
|
* @param {Object} message Message object to send
|
|
125
129
|
*/
|
|
126
130
|
sendRaw(message) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
{
|
|
131
|
+
let payload;
|
|
132
|
+
try {
|
|
133
|
+
payload = {
|
|
130
134
|
TERA: 1,
|
|
131
135
|
...cloneDeep(message), // Need to clone to resolve promise nasties
|
|
132
|
-
}
|
|
133
|
-
this.settings.restrictOrigin
|
|
134
|
-
)
|
|
136
|
+
};
|
|
137
|
+
globalThis.parent.postMessage(payload, this.settings.restrictOrigin);
|
|
138
|
+
} catch (e) {
|
|
139
|
+
this.debug('ERROR', 'Attempted to dispatch payload server->client', payload);
|
|
140
|
+
this.debug('ERROR', 'Message compose server->client:', e);
|
|
141
|
+
}
|
|
142
|
+
|
|
135
143
|
}
|
|
136
144
|
|
|
137
145
|
|
|
@@ -497,7 +505,18 @@ export default class TeraFyServer {
|
|
|
497
505
|
* @param {String} [msg...] Output to show
|
|
498
506
|
*/
|
|
499
507
|
debug(...msg) {
|
|
500
|
-
|
|
508
|
+
let method = 'log';
|
|
509
|
+
// Argument mangling for prefixing method {{{
|
|
510
|
+
if (typeof msg[0] == 'string' && ['INFO', 'LOG', 'WARN', 'ERROR'].includes(msg[0])) {
|
|
511
|
+
method = msg.shift().toLowerCase();
|
|
512
|
+
}
|
|
513
|
+
// }}}
|
|
514
|
+
|
|
515
|
+
if (
|
|
516
|
+
['INFO', 'LOG'].includes(method)
|
|
517
|
+
&& !this.settings.devMode
|
|
518
|
+
) return;
|
|
519
|
+
|
|
501
520
|
console.log(
|
|
502
521
|
'%c[TERA-FY SERVER]',
|
|
503
522
|
'font-weight: bold; color: #4d659c;',
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iebh/tera-fy",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "TERA website worker",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "esbuild --platform=browser --format=esm --bundle lib/terafy.client.js --outfile=dist/terafy.js --minify --sourcemap --serve --servedir=.",
|
|
7
7
|
"build": "concurrently 'npm:build:*'",
|
|
8
8
|
"build:client": "esbuild --platform=browser --format=esm --bundle lib/terafy.client.js --outfile=dist/terafy.js --minify --sourcemap",
|
|
9
|
-
"build:docs": "jsdoc2md --files lib/terafy.*.js
|
|
9
|
+
"build:docs": "jsdoc2md --files lib/terafy.*.js plugins/*.js >api.md",
|
|
10
10
|
"lint": "eslint ."
|
|
11
11
|
},
|
|
12
12
|
"type": "module",
|
package/plugins/vue.js
CHANGED
|
@@ -67,7 +67,7 @@ export default class TeraFyPluginVue extends TeraFyPluginBase {
|
|
|
67
67
|
* Provide a Vue@3 compatible plugin
|
|
68
68
|
*/
|
|
69
69
|
vuePlugin() {
|
|
70
|
-
let
|
|
70
|
+
let $tera = this;
|
|
71
71
|
|
|
72
72
|
return {
|
|
73
73
|
|
|
@@ -90,9 +90,14 @@ export default class TeraFyPluginVue extends TeraFyPluginBase {
|
|
|
90
90
|
...options,
|
|
91
91
|
};
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
// Make this module available globally
|
|
94
|
+
app.config.globalProperties[settings.globalName] = $tera;
|
|
95
|
+
|
|
96
|
+
// Bind $tera.state to the active project
|
|
97
|
+
// TODO: context.bindProjectState(settings.stateOptions),
|
|
98
|
+
$tera.state = {
|
|
99
|
+
id: 'TERAPROJ',
|
|
100
|
+
name: 'A fake project',
|
|
96
101
|
};
|
|
97
102
|
},
|
|
98
103
|
|