@iebh/tera-fy 2.3.10 → 2.3.12
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/CHANGELOG.md +32 -0
- package/api.md +8 -11
- package/dist/plugin.vue2.es2019.js +28 -27
- package/dist/terafy.bootstrapper.es2019.js +2 -2
- package/dist/terafy.bootstrapper.js +2 -2
- package/dist/terafy.es2019.js +5 -5
- package/dist/terafy.js +5 -5
- package/eslint.config.js +4 -66
- package/lib/{projectFile.ts → projectFile.js} +52 -76
- package/lib/syncro/{entities.ts → entities.js} +14 -83
- package/lib/syncro/{keyed.ts → keyed.js} +46 -68
- package/lib/syncro/{syncro.ts → syncro.js} +104 -136
- package/lib/{terafy.bootstrapper.ts → terafy.bootstrapper.js} +20 -30
- package/lib/{terafy.client.ts → terafy.client.js} +85 -84
- package/lib/{terafy.proxy.ts → terafy.proxy.js} +12 -26
- package/lib/{terafy.server.ts → terafy.server.js} +204 -229
- package/package.json +20 -39
- package/plugins/{base.ts → base.js} +3 -5
- package/plugins/{firebase.ts → firebase.js} +22 -21
- package/plugins/{vite.ts → vite.js} +3 -3
- package/plugins/{vue2.ts → vue2.js} +8 -10
- package/plugins/{vue3.ts → vue3.js} +7 -10
- package/utils/mixin.js +15 -0
- package/utils/{pathTools.ts → pathTools.js} +8 -9
- package/widgets/tera-file-select.vue +1 -1
- package/dist/lib/projectFile.d.ts +0 -190
- package/dist/lib/projectFile.js +0 -305
- package/dist/lib/projectFile.js.map +0 -1
- package/dist/lib/syncro/entities.d.ts +0 -34
- package/dist/lib/syncro/entities.js +0 -212
- package/dist/lib/syncro/entities.js.map +0 -1
- package/dist/lib/syncro/keyed (Rhino's conflicted copy 2026-05-10).js +0 -287
- package/dist/lib/syncro/keyed.d.ts +0 -95
- package/dist/lib/syncro/keyed.js +0 -288
- package/dist/lib/syncro/keyed.js (Rhino's conflicted copy 2026-05-10).map +0 -1
- package/dist/lib/syncro/keyed.js.map +0 -1
- package/dist/lib/syncro/syncro (Rhino's conflicted copy 2026-05-10).js +0 -765
- package/dist/lib/syncro/syncro.d (Rhino's conflicted copy 2026-05-10).ts +0 -336
- package/dist/lib/syncro/syncro.d.ts +0 -343
- package/dist/lib/syncro/syncro.js +0 -771
- package/dist/lib/syncro/syncro.js (Rhino's conflicted copy 2026-05-10).map +0 -1
- package/dist/lib/syncro/syncro.js.map +0 -1
- package/dist/lib/terafy.bootstrapper.d.ts +0 -42
- package/dist/lib/terafy.bootstrapper.js +0 -129
- package/dist/lib/terafy.bootstrapper.js.map +0 -1
- package/dist/lib/terafy.client.d.ts +0 -555
- package/dist/lib/terafy.client.js +0 -1153
- package/dist/lib/terafy.client.js.map +0 -1
- package/dist/lib/terafy.proxy.d.ts +0 -66
- package/dist/lib/terafy.proxy.js +0 -130
- package/dist/lib/terafy.proxy.js.map +0 -1
- package/dist/lib/terafy.server.d.ts +0 -697
- package/dist/lib/terafy.server.js +0 -2062
- package/dist/lib/terafy.server.js.map +0 -1
- package/dist/plugin.vue2.es2019 (Rhino's conflicted copy 2026-05-10).js +0 -1271
- package/dist/plugins/base.d.ts +0 -20
- package/dist/plugins/base.js +0 -22
- package/dist/plugins/base.js.map +0 -1
- package/dist/plugins/firebase.d.ts +0 -62
- package/dist/plugins/firebase.js +0 -123
- package/dist/plugins/firebase.js.map +0 -1
- package/dist/plugins/vite.d.ts +0 -12
- package/dist/plugins/vite.js +0 -22
- package/dist/plugins/vite.js.map +0 -1
- package/dist/plugins/vue2.d.ts +0 -67
- package/dist/plugins/vue2.js +0 -104
- package/dist/plugins/vue2.js.map +0 -1
- package/dist/plugins/vue3.d.ts +0 -63
- package/dist/plugins/vue3.js +0 -93
- package/dist/plugins/vue3.js.map +0 -1
- package/dist/utils/mixin.d.ts +0 -11
- package/dist/utils/mixin.js +0 -15
- package/dist/utils/mixin.js.map +0 -1
- package/dist/utils/pDefer.d.ts +0 -16
- package/dist/utils/pDefer.js +0 -19
- package/dist/utils/pDefer.js.map +0 -1
- package/dist/utils/pathTools.d.ts +0 -70
- package/dist/utils/pathTools.js +0 -120
- package/dist/utils/pathTools.js.map +0 -1
- package/tsconfig.json +0 -30
- package/utils/mixin.ts +0 -18
- package/utils/pDefer.ts +0 -27
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
import {merge} from 'lodash-es';
|
|
2
|
-
import type { default as TeraClient } from './terafy.client.js';
|
|
3
|
-
|
|
4
|
-
// Define interface for deferred methods
|
|
5
|
-
interface DeferredMethod {
|
|
6
|
-
method: string;
|
|
7
|
-
args: any[];
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
type TeraClientConstructor = typeof TeraClient
|
|
11
2
|
|
|
12
3
|
|
|
13
4
|
/**
|
|
@@ -17,7 +8,7 @@ type TeraClientConstructor = typeof TeraClient
|
|
|
17
8
|
* @class TeraFy
|
|
18
9
|
*/
|
|
19
10
|
export default class TeraFy {
|
|
20
|
-
settings
|
|
11
|
+
settings = { // Added index signature for merge compatibility
|
|
21
12
|
client: 'tera-fy', // Client name within https://tera-tools.com/api/tera-fy/<NAME>.js to load
|
|
22
13
|
clientType: 'esm',
|
|
23
14
|
};
|
|
@@ -29,18 +20,18 @@ export default class TeraFy {
|
|
|
29
20
|
* @param {Object} [options] Additional options to merge into `settings` via `set`
|
|
30
21
|
* @returns {Promise<TeraFy>} An eventual promise which will resolve with this terafy instance
|
|
31
22
|
*/
|
|
32
|
-
init(options
|
|
23
|
+
init(options) {
|
|
33
24
|
// FIXME: Note this needs to point at the live site
|
|
34
|
-
const getUrl =
|
|
25
|
+
const getUrl = client => `https://dev.tera-tools.com/api/tera-fy/${client}.js`;
|
|
35
26
|
|
|
36
27
|
return Promise.resolve()
|
|
37
|
-
.then(()=>
|
|
28
|
+
.then(()=> /* eslint-disable @stylistic/indent */
|
|
38
29
|
this.settings.clientType == 'esm' ?
|
|
39
30
|
this.bootstrapperImport(getUrl(this.settings.client))
|
|
40
31
|
.then(exported => typeof exported == 'function' ? exported : Promise.reject("Tera-fy import didn't return a class"))
|
|
41
32
|
: Promise.reject(`Unsupported TERA-fy clientType "${this.settings.clientType}"`)
|
|
42
33
|
)
|
|
43
|
-
.then(
|
|
34
|
+
.then(TeraClient => {
|
|
44
35
|
const tc = new TeraClient();
|
|
45
36
|
if (!tc.mixin) throw new Error("TERA-fy client doesn't expose a mixin() method");
|
|
46
37
|
|
|
@@ -51,28 +42,28 @@ export default class TeraFy {
|
|
|
51
42
|
})
|
|
52
43
|
.then(()=> { // Sanity checks
|
|
53
44
|
console.log('IAM', this);
|
|
54
|
-
if (!
|
|
55
|
-
if (!
|
|
45
|
+
if (!this.init || typeof this.init != 'function') throw new Error("Newly mixed-in TERA-fy client doesn't expose a init() method");
|
|
46
|
+
if (!this.detectMode || typeof this.detectMode != 'function') throw new Error("Newly mixed-in TERA-fy client doesn't expose a detectMode() method");
|
|
56
47
|
})
|
|
57
48
|
// Run all deferred methods as an sequential promise chain
|
|
58
|
-
.then(() => this.bootstrapperDeferredMethods.reduce((chain
|
|
49
|
+
.then(() => this.bootstrapperDeferredMethods.reduce((chain, dm) => {
|
|
59
50
|
return chain.then(() => {
|
|
60
51
|
if (dm.method == 'use' && typeof dm.args[0] == 'string') { // Wrap `use(pluginClient:String,options:Object)` method to fetch plugin from remote
|
|
61
52
|
console.log('TERA-FY DEFERRED-USE', dm.args[0]);
|
|
62
53
|
return this.bootstrapperImport(getUrl(dm.args[0]))
|
|
63
54
|
.then(exported => typeof exported == 'function' ? exported : Promise.reject("Tera-fy plugin import didn't return a class"))
|
|
64
|
-
.then(mod =>
|
|
55
|
+
.then(mod => this.use(mod, ...dm.args.slice(1)));
|
|
65
56
|
} else {
|
|
66
57
|
console.log('TERA-FY DEFERRED-METHOD', dm);
|
|
67
58
|
// Assuming the deferred method might return a promise or a value
|
|
68
|
-
return Promise.resolve(
|
|
59
|
+
return Promise.resolve(this[dm.method].apply(this, dm.args));
|
|
69
60
|
}
|
|
70
61
|
});
|
|
71
62
|
}, Promise.resolve())) // Initialize reduce chain correctly
|
|
72
|
-
.then(()=> { delete
|
|
63
|
+
.then(()=> { delete this.bootstrapperDeferredMethods; })
|
|
73
64
|
.then(()=> console.log('TYBS', 'Init'))
|
|
74
65
|
// Call the *actual* init method mixed in from the client
|
|
75
|
-
.then(()
|
|
66
|
+
.then(()=> this.init.call(this, options))
|
|
76
67
|
.then(() => this); // Ensure the promise chain resolves with `this`
|
|
77
68
|
}
|
|
78
69
|
|
|
@@ -83,7 +74,7 @@ export default class TeraFy {
|
|
|
83
74
|
*
|
|
84
75
|
* @type {Array<Object>}
|
|
85
76
|
*/
|
|
86
|
-
bootstrapperDeferredMethods
|
|
77
|
+
bootstrapperDeferredMethods = [];
|
|
87
78
|
|
|
88
79
|
|
|
89
80
|
/**
|
|
@@ -93,7 +84,7 @@ export default class TeraFy {
|
|
|
93
84
|
* @param {String} url The URL to import
|
|
94
85
|
* @returns {*} The default, single export of the module
|
|
95
86
|
*/
|
|
96
|
-
bootstrapperImport(url
|
|
87
|
+
bootstrapperImport(url) {
|
|
97
88
|
return new Promise((resolve, reject) => {
|
|
98
89
|
// Create a unique module ID
|
|
99
90
|
const moduleId = `installTFyBS${Math.random().toString(36).slice(2)}`;
|
|
@@ -108,22 +99,21 @@ export default class TeraFy {
|
|
|
108
99
|
|
|
109
100
|
// Create cleanup function
|
|
110
101
|
const cleanup = () => {
|
|
111
|
-
|
|
112
|
-
delete (window as any)[`installMod${moduleId}`]; // Use type assertion for delete
|
|
102
|
+
delete window[`installMod${moduleId}`];
|
|
113
103
|
if (script.parentNode) { // Check if script is still in DOM
|
|
114
104
|
script.remove();
|
|
115
105
|
}
|
|
116
106
|
}
|
|
117
107
|
|
|
118
108
|
// Create stub function to accept payload + quit
|
|
119
|
-
|
|
109
|
+
window[`installMod${moduleId}`] = payload => {
|
|
120
110
|
console.log('Accept module from', url, '=', payload);
|
|
121
111
|
resolve(payload);
|
|
122
112
|
cleanup();
|
|
123
113
|
};
|
|
124
114
|
|
|
125
115
|
|
|
126
|
-
script.addEventListener('error',
|
|
116
|
+
script.addEventListener('error', event => {
|
|
127
117
|
reject(new Error(`Failed to load module script from ${url}. Event type: ${event.type}`));
|
|
128
118
|
cleanup();
|
|
129
119
|
});
|
|
@@ -139,16 +129,16 @@ export default class TeraFy {
|
|
|
139
129
|
*
|
|
140
130
|
* @param {String} [options] Optional settings to merge
|
|
141
131
|
*/
|
|
142
|
-
constructor(options
|
|
132
|
+
constructor(options) {
|
|
143
133
|
// Merge options if provided
|
|
144
134
|
if (options) merge(this.settings, options);
|
|
145
135
|
|
|
146
136
|
// Map various methods to a deferred process so we execute these after init() has grabbed the actual TeraFyClient
|
|
147
137
|
['set', 'setIfDev', 'use'].forEach(m => {
|
|
148
|
-
|
|
138
|
+
this[m] = (...args) => {
|
|
149
139
|
this.bootstrapperDeferredMethods.push({method: m, args});
|
|
150
140
|
return this;
|
|
151
141
|
}
|
|
152
142
|
});
|
|
153
143
|
}
|
|
154
|
-
}
|
|
144
|
+
}
|
|
@@ -3,6 +3,9 @@ import Mitt from 'mitt';
|
|
|
3
3
|
import {nanoid} from 'nanoid';
|
|
4
4
|
import ProjectFile from './projectFile.js';
|
|
5
5
|
|
|
6
|
+
/* globals window */
|
|
7
|
+
|
|
8
|
+
|
|
6
9
|
/**
|
|
7
10
|
* Main Tera-Fy Client (class singleton) to be used in a frontend browser
|
|
8
11
|
*
|
|
@@ -28,22 +31,21 @@ export default class TeraFy {
|
|
|
28
31
|
* @property {Array<String|Array<String>>} [debugPaths] List of paths (in either dotted or array notation) to enter debugging mode if a change is detected in dev mode e.g. `{debugPaths: ['foo.bar.baz']}`. This really slows down state writes so should only be used for debugging
|
|
29
32
|
*/
|
|
30
33
|
settings = {
|
|
31
|
-
session: null
|
|
34
|
+
session: null,
|
|
32
35
|
// client: 'tera-fy', // Reserved by terafy.bootstrapper.js
|
|
33
36
|
// clientType: 'esm', // Reserved by terafy.bootstrapper.js
|
|
34
37
|
devMode: false,
|
|
35
38
|
verbosity: 1,
|
|
36
|
-
mode: 'detect'
|
|
39
|
+
mode: 'detect',
|
|
37
40
|
modeTimeout: 300,
|
|
38
41
|
modeFallback: 'child', // ENUM: 'child' (use iframes), 'popup' (use popup windows)
|
|
39
42
|
modeOverrides: {
|
|
40
|
-
child(config
|
|
43
|
+
child(config) { // When we're in child mode assume a local dev environment and use the dev.tera-tools.com site instead to work around CORS restrictions
|
|
41
44
|
if (config.siteUrl == 'https://tera-tools.com/embed') { // Only if we're using the default URL...
|
|
42
45
|
config.siteUrl = 'https://dev.tera-tools.com/embed'; // Repoint URL to dev site
|
|
43
46
|
}
|
|
44
47
|
},
|
|
45
|
-
|
|
46
|
-
} as { [key: string]: (config: any) => void },
|
|
48
|
+
},
|
|
47
49
|
siteUrl: 'https://tera-tools.com/embed',
|
|
48
50
|
restrictOrigin: '*',
|
|
49
51
|
frameSandbox: [
|
|
@@ -60,7 +62,7 @@ export default class TeraFy {
|
|
|
60
62
|
],
|
|
61
63
|
handshakeInterval: 1000, // ~1s
|
|
62
64
|
handshakeTimeout: 10_000, // ~10s
|
|
63
|
-
debugPaths: null
|
|
65
|
+
debugPaths: null, // Transformed into a Array<String> (in Lodash dotted notation) on init()
|
|
64
66
|
};
|
|
65
67
|
|
|
66
68
|
|
|
@@ -68,7 +70,6 @@ export default class TeraFy {
|
|
|
68
70
|
* Event emitter subscription endpoint
|
|
69
71
|
* @type {Mitt}
|
|
70
72
|
*/
|
|
71
|
-
// @ts-ignore - Because mitt is exported as cjs typescript has trouble resolving default export
|
|
72
73
|
events = Mitt();
|
|
73
74
|
|
|
74
75
|
|
|
@@ -82,10 +83,10 @@ export default class TeraFy {
|
|
|
82
83
|
* @property {DOMElement} stylesheet The corresponding stylesheet
|
|
83
84
|
*/
|
|
84
85
|
dom = {
|
|
85
|
-
el: null
|
|
86
|
-
iframe: null
|
|
87
|
-
popup: null
|
|
88
|
-
stylesheet: null
|
|
86
|
+
el: null,
|
|
87
|
+
iframe: null,
|
|
88
|
+
popup: null,
|
|
89
|
+
stylesheet: null,
|
|
89
90
|
};
|
|
90
91
|
|
|
91
92
|
|
|
@@ -162,14 +163,14 @@ export default class TeraFy {
|
|
|
162
163
|
'uiThrow',
|
|
163
164
|
'uiSplat',
|
|
164
165
|
'uiWindow',
|
|
165
|
-
]
|
|
166
|
+
];
|
|
166
167
|
|
|
167
168
|
|
|
168
169
|
/**
|
|
169
170
|
* Loaded plugins via Use()
|
|
170
171
|
* @type {Array<TeraFyPlugin>}
|
|
171
172
|
*/
|
|
172
|
-
plugins
|
|
173
|
+
plugins = [];
|
|
173
174
|
|
|
174
175
|
|
|
175
176
|
/**
|
|
@@ -177,9 +178,9 @@ export default class TeraFy {
|
|
|
177
178
|
* Each key is the namespace name with the value as the local reactive \ observer \ object equivalent
|
|
178
179
|
* The key string is always of the form `${ENTITY}::${ID}` e.g. `projects:1234`
|
|
179
180
|
*
|
|
180
|
-
* @type {Object
|
|
181
|
+
* @type {Object}
|
|
181
182
|
*/
|
|
182
|
-
namespaces
|
|
183
|
+
namespaces = {};
|
|
183
184
|
|
|
184
185
|
|
|
185
186
|
// Messages - send(), sendRaw(), rpc(), acceptMessage() {{{
|
|
@@ -190,7 +191,7 @@ export default class TeraFy {
|
|
|
190
191
|
* @param {Object} message Message object to send
|
|
191
192
|
* @returns {Promise<*>} A promise which resolves when the operation has completed with the remote reply
|
|
192
193
|
*/
|
|
193
|
-
send(message
|
|
194
|
+
send(message) {
|
|
194
195
|
const id = nanoid();
|
|
195
196
|
|
|
196
197
|
this.acceptPostboxes[id] = {}; // Stub for the deferred promise
|
|
@@ -214,8 +215,8 @@ export default class TeraFy {
|
|
|
214
215
|
*
|
|
215
216
|
* @param {Object} message Message object to send
|
|
216
217
|
*/
|
|
217
|
-
sendRaw(message
|
|
218
|
-
let payload
|
|
218
|
+
sendRaw(message) {
|
|
219
|
+
let payload;
|
|
219
220
|
try {
|
|
220
221
|
payload = {
|
|
221
222
|
TERA: 1,
|
|
@@ -226,13 +227,12 @@ export default class TeraFy {
|
|
|
226
227
|
if (this.settings.mode == 'parent') {
|
|
227
228
|
window.parent.postMessage(payload, this.settings.restrictOrigin);
|
|
228
229
|
} else if (this.settings.mode == 'child') {
|
|
229
|
-
this.dom.iframe
|
|
230
|
+
this.dom.iframe.contentWindow.postMessage(payload, this.settings.restrictOrigin);
|
|
230
231
|
} else if (this.settings.mode == 'popup') {
|
|
231
|
-
this.dom.popup
|
|
232
|
+
this.dom.popup.postMessage(payload, this.settings.restrictOrigin);
|
|
232
233
|
} else if (this.settings.mode == 'detect') {
|
|
233
234
|
throw new Error('Call init() or detectMode() before trying to send data to determine the mode');
|
|
234
235
|
} else {
|
|
235
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
236
236
|
throw new Error(`Unknown TERA communication mode "${this.settings.mode}"`);
|
|
237
237
|
}
|
|
238
238
|
} catch (e) {
|
|
@@ -251,7 +251,7 @@ export default class TeraFy {
|
|
|
251
251
|
*
|
|
252
252
|
* @returns {Promise<*>} The resolved output of the server function
|
|
253
253
|
*/
|
|
254
|
-
rpc(method
|
|
254
|
+
rpc(method, ...args) {
|
|
255
255
|
return this.send({
|
|
256
256
|
action: 'rpc',
|
|
257
257
|
method,
|
|
@@ -267,7 +267,7 @@ export default class TeraFy {
|
|
|
267
267
|
*
|
|
268
268
|
* @returns {Promise} A promise which will resolve when the message has been processed
|
|
269
269
|
*/
|
|
270
|
-
acceptMessage(rawMessage
|
|
270
|
+
acceptMessage(rawMessage) {
|
|
271
271
|
if (rawMessage.origin == window.location.origin) return Promise.resolve(); // Message came from us
|
|
272
272
|
|
|
273
273
|
const message = rawMessage.data;
|
|
@@ -283,7 +283,7 @@ export default class TeraFy {
|
|
|
283
283
|
return Promise.resolve();
|
|
284
284
|
} else if (message?.action == 'rpc') {
|
|
285
285
|
return Promise.resolve()
|
|
286
|
-
.then(()=>
|
|
286
|
+
.then(()=> this[message.method].apply(this, message.args))
|
|
287
287
|
.then(res => this.sendRaw({
|
|
288
288
|
id: message.id,
|
|
289
289
|
action: 'response',
|
|
@@ -300,7 +300,7 @@ export default class TeraFy {
|
|
|
300
300
|
})
|
|
301
301
|
} else if (message?.action == 'event') {
|
|
302
302
|
return Promise.resolve()
|
|
303
|
-
.then(()=> this.events.emit(message.event, ...
|
|
303
|
+
.then(()=> this.events.emit(message.event, ...message.payload))
|
|
304
304
|
.catch(e => {
|
|
305
305
|
console.warn(`TERA-FY client threw while handling emitted event "${message.event}"`, {message});
|
|
306
306
|
throw e;
|
|
@@ -318,7 +318,7 @@ export default class TeraFy {
|
|
|
318
318
|
/**
|
|
319
319
|
* Listening postboxes, these correspond to outgoing message IDs that expect a response
|
|
320
320
|
*/
|
|
321
|
-
acceptPostboxes
|
|
321
|
+
acceptPostboxes = {};
|
|
322
322
|
|
|
323
323
|
// }}}
|
|
324
324
|
|
|
@@ -332,7 +332,7 @@ export default class TeraFy {
|
|
|
332
332
|
*
|
|
333
333
|
* @returns {Promise<Reactive>} A promise which resolves to the reactive object
|
|
334
334
|
*/
|
|
335
|
-
mountNamespace(name
|
|
335
|
+
mountNamespace(name) {
|
|
336
336
|
if (!/^[\w-]+$/.test(name)) throw new Error('Namespaces must be alphanumeric + hyphens + underscores');
|
|
337
337
|
if (this.namespaces[name]) return Promise.resolve(this.namespaces[name]); // Already mounted
|
|
338
338
|
|
|
@@ -350,7 +350,7 @@ export default class TeraFy {
|
|
|
350
350
|
*
|
|
351
351
|
* @returns {Promise} A promise which resolves when the mount operation has completed
|
|
352
352
|
*/
|
|
353
|
-
_mountNamespace(name
|
|
353
|
+
_mountNamespace(name) {
|
|
354
354
|
console.warn(`teraFy._mountNamespace() for ${name} has not been overridden by a TERA-fy plugin, load one to add this functionality for your preferred framework`);
|
|
355
355
|
throw new Error('teraFy._mountNamespace() is not supported');
|
|
356
356
|
}
|
|
@@ -366,7 +366,7 @@ export default class TeraFy {
|
|
|
366
366
|
*
|
|
367
367
|
* @returns {Promise} A promise which resolves when the operation has completed
|
|
368
368
|
*/
|
|
369
|
-
unmountNamespace(name
|
|
369
|
+
unmountNamespace(name) {
|
|
370
370
|
if (!this.namespaces[name]) return Promise.resolve(); // Already unmounted
|
|
371
371
|
return this._unmountNamespace(name);
|
|
372
372
|
}
|
|
@@ -380,7 +380,7 @@ export default class TeraFy {
|
|
|
380
380
|
*
|
|
381
381
|
* @returns {Promise} A promise which resolves when the operation has completed
|
|
382
382
|
*/
|
|
383
|
-
_unmountNamespace(name
|
|
383
|
+
_unmountNamespace(name) {
|
|
384
384
|
console.warn(`teraFy.unbindNamespace() for ${name} has not been overridden by a TERA-fy plugin, load one to add this functionality for your preferred framework`);
|
|
385
385
|
}
|
|
386
386
|
// }}}
|
|
@@ -392,11 +392,11 @@ export default class TeraFy {
|
|
|
392
392
|
*
|
|
393
393
|
* @param {Object} [options] Additional options to merge into `settings` via `set`
|
|
394
394
|
*/
|
|
395
|
-
constructor(options
|
|
395
|
+
constructor(options) {
|
|
396
396
|
if (options) this.set(options);
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
-
|
|
399
|
+
initPromise = null;
|
|
400
400
|
|
|
401
401
|
/**
|
|
402
402
|
* Initialize the TERA client singleton
|
|
@@ -405,22 +405,21 @@ export default class TeraFy {
|
|
|
405
405
|
* @param {Object} [options] Additional options to merge into `settings` via `set`
|
|
406
406
|
* @returns {Promise<TeraFy>} An eventual promise which will resolve with this terafy instance
|
|
407
407
|
*/
|
|
408
|
-
init(options
|
|
408
|
+
init(options) {
|
|
409
409
|
if (options) this.set(options);
|
|
410
410
|
if (this.initPromise) return this.initPromise; // Already been called - return init promise
|
|
411
411
|
|
|
412
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
413
412
|
window.addEventListener('message', this.acceptMessage.bind(this));
|
|
414
413
|
|
|
415
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
416
414
|
const context = this;
|
|
417
415
|
this.initPromise = Promise.resolve()
|
|
418
416
|
.then(()=> this.settings.session ||= 'tfy-' + this.getEntropicString(16))
|
|
419
417
|
.then(()=> this.debug('INFO', 4, '[0/6] Init', 'Session', this.settings.session, 'against', this.settings.siteUrl))
|
|
420
418
|
.then(()=> { // Init various options for optimized access
|
|
419
|
+
/* eslint-disable @stylistic/indent */
|
|
421
420
|
if (!this.settings.devMode) return; // Not in dev mode
|
|
422
|
-
if (this.settings.debugPaths) {
|
|
423
|
-
this.settings.debugPaths =
|
|
421
|
+
if (this.settings.debugPaths) { // eslint-disable-line unicorn/prefer-ternary
|
|
422
|
+
this.settings.debugPaths = this.settings.debugPaths.map(path =>
|
|
424
423
|
Array.isArray(path) ? path.join('.') // Transform arrays into dotted notation
|
|
425
424
|
: typeof path == 'string' ? path // Assume already in dotted notation
|
|
426
425
|
: (()=> { throw new Error('Unknown path type - should be an array or string in dotted notation') })()
|
|
@@ -483,22 +482,21 @@ export default class TeraFy {
|
|
|
483
482
|
}
|
|
484
483
|
|
|
485
484
|
|
|
486
|
-
|
|
487
485
|
/**
|
|
488
486
|
* Populate `settings.mode`
|
|
489
487
|
* Try to communicate with a parent frame, if none assume we need to fallback to child mode
|
|
490
488
|
*
|
|
491
489
|
* @returns {Promise<String>} A promise which will resolve with the detected mode to use
|
|
492
490
|
*/
|
|
493
|
-
detectMode()
|
|
491
|
+
detectMode() {
|
|
494
492
|
if (this.settings.mode != 'detect') { // Dev has specified a forced mode to use
|
|
495
493
|
return Promise.resolve(this.settings.mode);
|
|
496
494
|
} else if (window.self === window.parent) { // This frame is already at the top
|
|
497
|
-
return Promise.resolve(this.settings.modeFallback
|
|
495
|
+
return Promise.resolve(this.settings.modeFallback);
|
|
498
496
|
} else { // No idea - try messaging
|
|
499
497
|
return Promise.resolve()
|
|
500
498
|
.then(()=> this.settings.mode = 'parent') // Switch to parent mode...
|
|
501
|
-
.then(()=> new Promise
|
|
499
|
+
.then(()=> new Promise((resolve, reject) => { // And try messaging with a timeout
|
|
502
500
|
const timeoutHandle = setTimeout(()=> reject('TIMEOUT'), this.settings.modeTimeout);
|
|
503
501
|
|
|
504
502
|
this.rpc('handshake')
|
|
@@ -506,8 +504,8 @@ export default class TeraFy {
|
|
|
506
504
|
.then(()=> resolve())
|
|
507
505
|
.catch(reject); // Propagate RPC errors
|
|
508
506
|
}))
|
|
509
|
-
.then(()=> 'parent'
|
|
510
|
-
.catch(()=> this.settings.modeFallback
|
|
507
|
+
.then(()=> 'parent')
|
|
508
|
+
.catch(()=> this.settings.modeFallback)
|
|
511
509
|
}
|
|
512
510
|
}
|
|
513
511
|
|
|
@@ -520,7 +518,7 @@ export default class TeraFy {
|
|
|
520
518
|
injectComms() {
|
|
521
519
|
switch (this.settings.mode) {
|
|
522
520
|
case 'child': return Promise.resolve()
|
|
523
|
-
.then(()=> new Promise
|
|
521
|
+
.then(()=> new Promise(resolve => {
|
|
524
522
|
this.debug('INFO', 2, 'Injecting TERA site as iFrame child');
|
|
525
523
|
|
|
526
524
|
this.dom.el = document.createElement('div')
|
|
@@ -529,7 +527,7 @@ export default class TeraFy {
|
|
|
529
527
|
this.dom.el.classList.add('minimized');
|
|
530
528
|
document.body.append(this.dom.el);
|
|
531
529
|
|
|
532
|
-
this.dom.el.addEventListener('click', ()=> this.dom.el
|
|
530
|
+
this.dom.el.addEventListener('click', ()=> this.dom.el.classList.toggle('minimized'));
|
|
533
531
|
|
|
534
532
|
this.dom.iframe = document.createElement('iframe')
|
|
535
533
|
|
|
@@ -572,7 +570,7 @@ export default class TeraFy {
|
|
|
572
570
|
*
|
|
573
571
|
* @returns {Promise} A promise which will either resolve when the handshake is successful OR fail with 'TIMEOUT'
|
|
574
572
|
*/
|
|
575
|
-
handshakeLoop(options
|
|
573
|
+
handshakeLoop(options) {
|
|
576
574
|
const settings = {
|
|
577
575
|
handshakeInterval: this.settings.handshakeInterval,
|
|
578
576
|
handshakeTimeout: this.settings.handshakeTimeout,
|
|
@@ -580,9 +578,9 @@ export default class TeraFy {
|
|
|
580
578
|
};
|
|
581
579
|
|
|
582
580
|
// Loop until the window context returns a handshake
|
|
583
|
-
return new Promise
|
|
581
|
+
return new Promise((resolve, reject) => {
|
|
584
582
|
let handshakeCount = 0;
|
|
585
|
-
let handshakeTimer
|
|
583
|
+
let handshakeTimer;
|
|
586
584
|
|
|
587
585
|
const handshakeTimeout = setTimeout(()=> {
|
|
588
586
|
clearTimeout(handshakeTimer);
|
|
@@ -750,7 +748,7 @@ export default class TeraFy {
|
|
|
750
748
|
*/
|
|
751
749
|
injectMethods() {
|
|
752
750
|
this.methods.forEach(method =>
|
|
753
|
-
|
|
751
|
+
this[method] = this.rpc.bind(this, method)
|
|
754
752
|
);
|
|
755
753
|
return Promise.resolve();
|
|
756
754
|
}
|
|
@@ -767,7 +765,7 @@ export default class TeraFy {
|
|
|
767
765
|
* @param {Number} [verboseLevel=1] The verbosity level to trigger at. If `settings.verbosity` is lower than this, the message is ignored
|
|
768
766
|
* @param {...*} [msg] Output to show
|
|
769
767
|
*/
|
|
770
|
-
debug(...msg
|
|
768
|
+
debug(...msg) {
|
|
771
769
|
if (!this.settings.devMode || this.settings.verbosity < 1) return; // Debugging is disabled
|
|
772
770
|
let method = 'log';
|
|
773
771
|
let verboseLevel = 1;
|
|
@@ -784,7 +782,7 @@ export default class TeraFy {
|
|
|
784
782
|
|
|
785
783
|
if (this.settings.verbosity < verboseLevel) return; // Called but this output is too verbose for our settings - skip
|
|
786
784
|
|
|
787
|
-
|
|
785
|
+
console[method](
|
|
788
786
|
'%c[TERA-FY CLIENT]',
|
|
789
787
|
'font-weight: bold; color: #ff5722;',
|
|
790
788
|
...msg,
|
|
@@ -805,7 +803,7 @@ export default class TeraFy {
|
|
|
805
803
|
*
|
|
806
804
|
* @returns {TeraFy} This chainable terafy instance
|
|
807
805
|
*/
|
|
808
|
-
set(key
|
|
806
|
+
set(key, value, options) {
|
|
809
807
|
const settings = {
|
|
810
808
|
ignoreNullish: true,
|
|
811
809
|
...options,
|
|
@@ -813,7 +811,7 @@ export default class TeraFy {
|
|
|
813
811
|
|
|
814
812
|
if (typeof key == 'string') {
|
|
815
813
|
if (!settings.ignoreNullish || (value !== null && value !== undefined))
|
|
816
|
-
|
|
814
|
+
this.settings[key] = value;
|
|
817
815
|
} else {
|
|
818
816
|
Object.assign(this.settings, key);
|
|
819
817
|
}
|
|
@@ -832,7 +830,7 @@ export default class TeraFy {
|
|
|
832
830
|
*
|
|
833
831
|
* @returns {TeraFy} This chainable terafy instance
|
|
834
832
|
*/
|
|
835
|
-
setIfDev(key
|
|
833
|
+
setIfDev(key, value, options) {
|
|
836
834
|
if (!this.settings.devMode || value === undefined) return this;
|
|
837
835
|
return this.set(key, value, options);
|
|
838
836
|
}
|
|
@@ -846,8 +844,9 @@ export default class TeraFy {
|
|
|
846
844
|
*
|
|
847
845
|
* @returns {TeraFy} This chainable terafy instance
|
|
848
846
|
*/
|
|
849
|
-
use(source
|
|
850
|
-
|
|
847
|
+
use(source, options) {
|
|
848
|
+
/* eslint-disable @stylistic/indent */
|
|
849
|
+
const mod =
|
|
851
850
|
typeof source == 'function' ? new source(this, options)
|
|
852
851
|
: typeof source == 'object' ? source
|
|
853
852
|
: typeof source == 'string' ? (()=> { throw new Error('use(String) is not yet supported') })()
|
|
@@ -866,7 +865,7 @@ export default class TeraFy {
|
|
|
866
865
|
* @param {Object} target Installed class instance to extend
|
|
867
866
|
* @param {Object} source Initialized source object to extend from
|
|
868
867
|
*/
|
|
869
|
-
mixin(target
|
|
868
|
+
mixin(target, source) {
|
|
870
869
|
// Iterate through the source object upwards extracting each prototype
|
|
871
870
|
const prototypeStack = [];
|
|
872
871
|
let node = source;
|
|
@@ -910,7 +909,7 @@ export default class TeraFy {
|
|
|
910
909
|
*
|
|
911
910
|
* @returns {TeraFy} This chainable terafy instance
|
|
912
911
|
*/
|
|
913
|
-
toggleDevMode(devModeEnabled
|
|
912
|
+
toggleDevMode(devModeEnabled = 'toggle') {
|
|
914
913
|
if (devModeEnabled === 'toggle') {
|
|
915
914
|
this.settings.devMode = !this.settings.devMode;
|
|
916
915
|
} else if (devModeEnabled === 'proxy') {
|
|
@@ -939,7 +938,7 @@ export default class TeraFy {
|
|
|
939
938
|
*
|
|
940
939
|
* @param {String|Boolean} [isFocused='toggle'] Whether to fullscreen the embedded component
|
|
941
940
|
*/
|
|
942
|
-
toggleFocus(isFocused
|
|
941
|
+
toggleFocus(isFocused = 'toggle') {
|
|
943
942
|
this.debug('INFO', 2, 'Request focus', {isFocused});
|
|
944
943
|
globalThis.document.body.classList.toggle('tera-fy-focus', isFocused === 'toggle' ? undefined : isFocused);
|
|
945
944
|
}
|
|
@@ -1207,9 +1206,9 @@ export default class TeraFy {
|
|
|
1207
1206
|
*
|
|
1208
1207
|
* @returns {Promise<ProjectFile>} The eventually selected file, if in save mode new files are created as stubs
|
|
1209
1208
|
*/
|
|
1210
|
-
selectProjectFile(options
|
|
1209
|
+
selectProjectFile(options) {
|
|
1211
1210
|
return this.rpc('selectProjectFile', options)
|
|
1212
|
-
.then(
|
|
1211
|
+
.then(file => file
|
|
1213
1212
|
? new ProjectFile({
|
|
1214
1213
|
tera: this,
|
|
1215
1214
|
...file,
|
|
@@ -1230,9 +1229,9 @@ export default class TeraFy {
|
|
|
1230
1229
|
*
|
|
1231
1230
|
* @returns {Promise<Array<ProjectFile>>} A collection of project files for the given project
|
|
1232
1231
|
*/
|
|
1233
|
-
getProjectFiles(options
|
|
1232
|
+
getProjectFiles(options) {
|
|
1234
1233
|
return this.rpc('getProjectFiles', options)
|
|
1235
|
-
.then(
|
|
1234
|
+
.then(files => files.map(file =>
|
|
1236
1235
|
new ProjectFile({
|
|
1237
1236
|
tera: this,
|
|
1238
1237
|
...file,
|
|
@@ -1265,9 +1264,9 @@ export default class TeraFy {
|
|
|
1265
1264
|
*
|
|
1266
1265
|
* @returns {Promise<ProjectFile>} The eventual fetched ProjectFile (or requested subkey)
|
|
1267
1266
|
*/
|
|
1268
|
-
getProjectFile(name
|
|
1267
|
+
getProjectFile(name, options) {
|
|
1269
1268
|
return this.rpc('getProjectFile', name, options)
|
|
1270
|
-
.then(
|
|
1269
|
+
.then(file => file
|
|
1271
1270
|
? new ProjectFile({
|
|
1272
1271
|
tera: this,
|
|
1273
1272
|
...file,
|
|
@@ -1285,9 +1284,9 @@ export default class TeraFy {
|
|
|
1285
1284
|
* @param {String} name The name + relative directory path component
|
|
1286
1285
|
* @returns {Promise<ProjectFile>} The eventual ProjectFile created
|
|
1287
1286
|
*/
|
|
1288
|
-
createProjectFile(name
|
|
1287
|
+
createProjectFile(name) {
|
|
1289
1288
|
return this.rpc('createProjectFile', name)
|
|
1290
|
-
.then(
|
|
1289
|
+
.then(file => file
|
|
1291
1290
|
? new ProjectFile({
|
|
1292
1291
|
tera: this,
|
|
1293
1292
|
...file,
|
|
@@ -1296,6 +1295,7 @@ export default class TeraFy {
|
|
|
1296
1295
|
)
|
|
1297
1296
|
}
|
|
1298
1297
|
|
|
1298
|
+
|
|
1299
1299
|
/**
|
|
1300
1300
|
* Moves a project file to a new name/path.
|
|
1301
1301
|
* The file's unique ID (UUID) remains the same, but its 'name' (relative path) and associated properties will be updated.
|
|
@@ -1307,26 +1307,24 @@ export default class TeraFy {
|
|
|
1307
1307
|
*
|
|
1308
1308
|
* @param {Object} [options] Additional options to mutate behaviour.
|
|
1309
1309
|
* @param {Boolean} [options.autoRequire=true] Run `requireProject()` automatically before continuing.
|
|
1310
|
-
* @param {Boolean} [options.overwrite=true] If true (default), moving a file to a `newName` that already exists will overwrite the existing file.
|
|
1311
|
-
* This aligns with the default behavior of the underlying Supabase storage `move` operation.
|
|
1312
|
-
* If set to false, the function would ideally check and prevent overwrite, but current implementation relies on underlying storage behavior.
|
|
1310
|
+
* @param {Boolean} [options.overwrite=true] If true (default), moving a file to a `newName` that already exists will overwrite the existing file. This aligns with the default behavior of the underlying Supabase storage `move` operation. If set to false, the function would ideally check and prevent overwrite, but current implementation relies on underlying storage behavior.
|
|
1313
1311
|
*
|
|
1314
|
-
* @returns {Promise<ProjectFile
|
|
1315
|
-
* or null if the file could not be located post-move (e.g., if its ID changed unexpectedly or it was deleted).
|
|
1312
|
+
* @returns {Promise<ProjectFile|null>} A promise which resolves to the updated ProjectFile object for the moved file if found after the operation, or null if the file could not be located post-move (e.g., if its ID changed unexpectedly or it was deleted).
|
|
1316
1313
|
*/
|
|
1317
|
-
moveProjectFile(sourceId
|
|
1314
|
+
moveProjectFile(sourceId, newName, options) {
|
|
1318
1315
|
return this.rpc('moveProjectFile', sourceId, newName, options)
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1316
|
+
.then(fileData => { // fileData is the plain object from the server
|
|
1317
|
+
if (fileData) {
|
|
1318
|
+
return new ProjectFile({
|
|
1319
|
+
tera: this, // Pass the TeraFy client instance
|
|
1320
|
+
...fileData,
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
return null;
|
|
1324
|
+
});
|
|
1328
1325
|
}
|
|
1329
1326
|
|
|
1327
|
+
|
|
1330
1328
|
/**
|
|
1331
1329
|
* Remove a project file by its ID
|
|
1332
1330
|
*
|
|
@@ -1354,7 +1352,8 @@ export default class TeraFy {
|
|
|
1354
1352
|
* @returns {Promise} A promise which will resolve when the write operation has completed
|
|
1355
1353
|
*/
|
|
1356
1354
|
|
|
1357
|
-
|
|
1355
|
+
|
|
1356
|
+
/**
|
|
1358
1357
|
* Creates a new "folder" within the project's file storage.
|
|
1359
1358
|
* Folders in Supabase storage are typically represented by creating a placeholder file (e.g., .emptyFolderPlaceholder) within the desired path.
|
|
1360
1359
|
* This operation is idempotent: if the folder (via its placeholder) already exists, it will not error.
|
|
@@ -1367,7 +1366,8 @@ export default class TeraFy {
|
|
|
1367
1366
|
* @throws {Error} If no project is active (and autoRequire is false), or if folderPath is invalid, or if the creation fails.
|
|
1368
1367
|
*/
|
|
1369
1368
|
|
|
1370
|
-
|
|
1369
|
+
|
|
1370
|
+
/**
|
|
1371
1371
|
* Deletes a "folder" and all its contents from the project's file storage.
|
|
1372
1372
|
* This involves listing all files under the given folder path (prefix) and removing them.
|
|
1373
1373
|
*
|
|
@@ -1379,6 +1379,7 @@ export default class TeraFy {
|
|
|
1379
1379
|
* @throws {Error} If no project is active (and autoRequire is false), or if folderPath is invalid, or if deletion fails.
|
|
1380
1380
|
*/
|
|
1381
1381
|
|
|
1382
|
+
|
|
1382
1383
|
/**
|
|
1383
1384
|
* Prompt the user to select a library to operate on and return a array of references in a given format
|
|
1384
1385
|
*
|