@iebh/tera-fy 2.0.22 → 2.2.3
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 +38 -0
- package/api.md +375 -298
- package/dist/lib/projectFile.d.ts +182 -0
- package/dist/lib/projectFile.js +157 -0
- package/dist/lib/projectFile.js.map +1 -0
- package/dist/lib/syncro/entities.d.ts +28 -0
- package/dist/lib/syncro/entities.js +203 -0
- package/dist/lib/syncro/entities.js.map +1 -0
- package/dist/lib/syncro/keyed.d.ts +95 -0
- package/dist/lib/syncro/keyed.js +286 -0
- package/dist/lib/syncro/keyed.js.map +1 -0
- package/dist/lib/syncro/syncro.d.ts +328 -0
- package/dist/lib/syncro/syncro.js +633 -0
- package/dist/lib/syncro/syncro.js.map +1 -0
- package/dist/lib/terafy.bootstrapper.d.ts +42 -0
- package/dist/lib/terafy.bootstrapper.js +130 -0
- package/dist/lib/terafy.bootstrapper.js.map +1 -0
- package/dist/lib/terafy.client.d.ts +552 -0
- package/dist/lib/terafy.client.js +1144 -0
- package/dist/lib/terafy.client.js.map +1 -0
- package/dist/lib/terafy.proxy.d.ts +66 -0
- package/dist/lib/terafy.proxy.js +123 -0
- package/dist/lib/terafy.proxy.js.map +1 -0
- package/dist/lib/terafy.server.d.ts +652 -0
- package/dist/lib/terafy.server.js +1988 -0
- package/dist/lib/terafy.server.js.map +1 -0
- package/dist/plugin.vue2.es2019.js +30 -13
- package/dist/plugins/base.d.ts +20 -0
- package/dist/plugins/base.js +21 -0
- package/dist/plugins/base.js.map +1 -0
- package/dist/plugins/firebase.d.ts +62 -0
- package/dist/plugins/firebase.js +111 -0
- package/dist/plugins/firebase.js.map +1 -0
- package/dist/plugins/vite.d.ts +12 -0
- package/dist/plugins/vite.js +22 -0
- package/dist/plugins/vite.js.map +1 -0
- package/dist/plugins/vue2.d.ts +68 -0
- package/dist/plugins/vue2.js +96 -0
- package/dist/plugins/vue2.js.map +1 -0
- package/dist/plugins/vue3.d.ts +64 -0
- package/dist/plugins/vue3.js +96 -0
- package/dist/plugins/vue3.js.map +1 -0
- package/dist/terafy.bootstrapper.es2019.js +2 -2
- package/dist/terafy.bootstrapper.js +2 -2
- package/dist/terafy.es2019.js +2 -2
- package/dist/terafy.js +2 -2
- package/dist/utils/mixin.d.ts +11 -0
- package/dist/utils/mixin.js +15 -0
- package/dist/utils/mixin.js.map +1 -0
- package/dist/utils/pDefer.d.ts +12 -0
- package/dist/utils/pDefer.js +14 -0
- package/dist/utils/pDefer.js.map +1 -0
- package/dist/utils/pathTools.d.ts +70 -0
- package/dist/utils/pathTools.js +120 -0
- package/dist/utils/pathTools.js.map +1 -0
- package/documentation.yml +3 -0
- package/eslint.config.js +44 -8
- package/lib/{projectFile.js → projectFile.ts} +83 -40
- package/lib/syncro/entities.ts +288 -0
- package/lib/syncro/{keyed.js → keyed.ts} +114 -57
- package/lib/syncro/{syncro.js → syncro.ts} +201 -168
- package/lib/{terafy.bootstrapper.js → terafy.bootstrapper.ts} +49 -31
- package/lib/{terafy.client.js → terafy.client.ts} +153 -86
- package/lib/{terafy.proxy.js → terafy.proxy.ts} +43 -16
- package/lib/{terafy.server.js → terafy.server.ts} +606 -223
- package/package.json +65 -26
- package/plugins/{base.js → base.ts} +3 -1
- package/plugins/{firebase.js → firebase.ts} +34 -16
- package/plugins/{vite.js → vite.ts} +3 -3
- package/plugins/{vue2.js → vue2.ts} +17 -10
- package/plugins/{vue3.js → vue3.ts} +11 -9
- package/tsconfig.json +30 -0
- package/utils/{mixin.js → mixin.ts} +1 -1
- package/utils/{pDefer.js → pDefer.ts} +10 -3
- package/utils/{pathTools.js → pathTools.ts} +11 -9
- package/lib/syncro/entities.js +0 -232
|
@@ -31,21 +31,21 @@ export default class TeraFy {
|
|
|
31
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
|
|
32
32
|
*/
|
|
33
33
|
settings = {
|
|
34
|
-
session: null,
|
|
34
|
+
session: null as string | null,
|
|
35
35
|
// client: 'tera-fy', // Reserved by terafy.bootstrapper.js
|
|
36
36
|
// clientType: 'esm', // Reserved by terafy.bootstrapper.js
|
|
37
37
|
devMode: false,
|
|
38
38
|
verbosity: 1,
|
|
39
|
-
mode: 'detect',
|
|
39
|
+
mode: 'detect' as 'detect' | 'parent' | 'child' | 'popup',
|
|
40
40
|
modeTimeout: 300,
|
|
41
41
|
modeFallback: 'child', // ENUM: 'child' (use iframes), 'popup' (use popup windows)
|
|
42
42
|
modeOverrides: {
|
|
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
|
|
43
|
+
child(config: any) { // 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
|
|
44
44
|
if (config.siteUrl == 'https://tera-tools.com/embed') { // Only if we're using the default URL...
|
|
45
45
|
config.siteUrl = 'https://dev.tera-tools.com/embed'; // Repoint URL to dev site
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
|
-
},
|
|
48
|
+
} as { [key: string]: (config: any) => void },
|
|
49
49
|
siteUrl: 'https://tera-tools.com/embed',
|
|
50
50
|
restrictOrigin: '*',
|
|
51
51
|
frameSandbox: [
|
|
@@ -62,7 +62,7 @@ export default class TeraFy {
|
|
|
62
62
|
],
|
|
63
63
|
handshakeInterval: 1_000, // ~1s
|
|
64
64
|
handshakeTimeout: 10_000, // ~10s
|
|
65
|
-
debugPaths: null, // Transformed into a Array<String> (in Lodash dotted notation) on init()
|
|
65
|
+
debugPaths: null as Array<string | Array<string>> | null, // Transformed into a Array<String> (in Lodash dotted notation) on init()
|
|
66
66
|
};
|
|
67
67
|
|
|
68
68
|
|
|
@@ -70,6 +70,7 @@ export default class TeraFy {
|
|
|
70
70
|
* Event emitter subscription endpoint
|
|
71
71
|
* @type {Mitt}
|
|
72
72
|
*/
|
|
73
|
+
// @ts-ignore
|
|
73
74
|
events = Mitt();
|
|
74
75
|
|
|
75
76
|
|
|
@@ -83,10 +84,10 @@ export default class TeraFy {
|
|
|
83
84
|
* @property {DOMElement} stylesheet The corresponding stylesheet
|
|
84
85
|
*/
|
|
85
86
|
dom = {
|
|
86
|
-
el: null,
|
|
87
|
-
iframe: null,
|
|
88
|
-
popup: null,
|
|
89
|
-
stylesheet: null,
|
|
87
|
+
el: null as HTMLDivElement | null,
|
|
88
|
+
iframe: null as HTMLIFrameElement | null,
|
|
89
|
+
popup: null as Window | null,
|
|
90
|
+
stylesheet: null as HTMLStyleElement | null,
|
|
90
91
|
};
|
|
91
92
|
|
|
92
93
|
|
|
@@ -133,9 +134,14 @@ export default class TeraFy {
|
|
|
133
134
|
// 'getProjectFile', - Handled below (requires return mapped to ProjectFile)
|
|
134
135
|
'getProjectFileContents',
|
|
135
136
|
// 'createProjectFile', - Handled below (requires return mapped to ProjectFile)
|
|
137
|
+
// 'moveProjectFile', - Handled below (requires return mapped to ProjectFile)
|
|
136
138
|
'deleteProjectFile',
|
|
137
139
|
'setProjectFileContents',
|
|
138
140
|
|
|
141
|
+
// Project folders
|
|
142
|
+
'createProjectFolder',
|
|
143
|
+
'deleteProjectFolder',
|
|
144
|
+
|
|
139
145
|
// Project Libraries
|
|
140
146
|
'selectProjectLibrary',
|
|
141
147
|
'getProjectLibrary',
|
|
@@ -156,14 +162,14 @@ export default class TeraFy {
|
|
|
156
162
|
'uiThrow',
|
|
157
163
|
'uiSplat',
|
|
158
164
|
'uiWindow',
|
|
159
|
-
];
|
|
165
|
+
] as const;
|
|
160
166
|
|
|
161
167
|
|
|
162
168
|
/**
|
|
163
169
|
* Loaded plugins via Use()
|
|
164
170
|
* @type {Array<TeraFyPlugin>}
|
|
165
171
|
*/
|
|
166
|
-
plugins = [];
|
|
172
|
+
plugins: any[] = [];
|
|
167
173
|
|
|
168
174
|
|
|
169
175
|
/**
|
|
@@ -173,7 +179,7 @@ export default class TeraFy {
|
|
|
173
179
|
*
|
|
174
180
|
* @type {Object<Object>}
|
|
175
181
|
*/
|
|
176
|
-
namespaces = {};
|
|
182
|
+
namespaces: { [key: string]: any } = {};
|
|
177
183
|
|
|
178
184
|
|
|
179
185
|
// Messages - send(), sendRaw(), rpc(), acceptMessage() {{{
|
|
@@ -184,7 +190,7 @@ export default class TeraFy {
|
|
|
184
190
|
* @param {Object} message Message object to send
|
|
185
191
|
* @returns {Promise<*>} A promise which resolves when the operation has completed with the remote reply
|
|
186
192
|
*/
|
|
187
|
-
send(message) {
|
|
193
|
+
send(message: any) {
|
|
188
194
|
let id = nanoid();
|
|
189
195
|
|
|
190
196
|
this.acceptPostboxes[id] = {}; // Stub for the deferred promise
|
|
@@ -208,8 +214,8 @@ export default class TeraFy {
|
|
|
208
214
|
*
|
|
209
215
|
* @param {Object} message Message object to send
|
|
210
216
|
*/
|
|
211
|
-
sendRaw(message) {
|
|
212
|
-
let payload;
|
|
217
|
+
sendRaw(message: any) {
|
|
218
|
+
let payload: any;
|
|
213
219
|
try {
|
|
214
220
|
payload = {
|
|
215
221
|
TERA: 1,
|
|
@@ -220,9 +226,9 @@ export default class TeraFy {
|
|
|
220
226
|
if (this.settings.mode == 'parent') {
|
|
221
227
|
window.parent.postMessage(payload, this.settings.restrictOrigin);
|
|
222
228
|
} else if (this.settings.mode == 'child') {
|
|
223
|
-
this.dom.iframe
|
|
229
|
+
this.dom.iframe!.contentWindow!.postMessage(payload, this.settings.restrictOrigin);
|
|
224
230
|
} else if (this.settings.mode == 'popup') {
|
|
225
|
-
this.dom.popup
|
|
231
|
+
this.dom.popup!.postMessage(payload, this.settings.restrictOrigin);
|
|
226
232
|
} else if (this.settings.mode == 'detect') {
|
|
227
233
|
throw new Error('Call init() or detectMode() before trying to send data to determine the mode');
|
|
228
234
|
} else {
|
|
@@ -244,7 +250,7 @@ export default class TeraFy {
|
|
|
244
250
|
*
|
|
245
251
|
* @returns {Promise<*>} The resolved output of the server function
|
|
246
252
|
*/
|
|
247
|
-
rpc(method, ...args) {
|
|
253
|
+
rpc(method: any, ...args: any[]) {
|
|
248
254
|
return this.send({
|
|
249
255
|
action: 'rpc',
|
|
250
256
|
method,
|
|
@@ -260,7 +266,7 @@ export default class TeraFy {
|
|
|
260
266
|
*
|
|
261
267
|
* @returns {Promise} A promise which will resolve when the message has been processed
|
|
262
268
|
*/
|
|
263
|
-
acceptMessage(rawMessage) {
|
|
269
|
+
acceptMessage(rawMessage: any) {
|
|
264
270
|
if (rawMessage.origin == window.location.origin) return Promise.resolve(); // Message came from us
|
|
265
271
|
|
|
266
272
|
let message = rawMessage.data;
|
|
@@ -276,7 +282,7 @@ export default class TeraFy {
|
|
|
276
282
|
return Promise.resolve();
|
|
277
283
|
} else if (message?.action == 'rpc') {
|
|
278
284
|
return Promise.resolve()
|
|
279
|
-
.then(()=> this[message.method].apply(this, message.args))
|
|
285
|
+
.then(()=> (this as any)[message.method].apply(this, message.args as any[]))
|
|
280
286
|
.then(res => this.sendRaw({
|
|
281
287
|
id: message.id,
|
|
282
288
|
action: 'response',
|
|
@@ -293,7 +299,7 @@ export default class TeraFy {
|
|
|
293
299
|
})
|
|
294
300
|
} else if (message?.action == 'event') {
|
|
295
301
|
return Promise.resolve()
|
|
296
|
-
.then(()=> this.events.emit(message.event, ...message.payload))
|
|
302
|
+
.then(()=> this.events.emit(message.event, ...(message.payload as [])))
|
|
297
303
|
.catch(e => {
|
|
298
304
|
console.warn(`TERA-FY client threw while handling emitted event "${message.event}"`, {message});
|
|
299
305
|
throw e;
|
|
@@ -311,7 +317,7 @@ export default class TeraFy {
|
|
|
311
317
|
/**
|
|
312
318
|
* Listening postboxes, these correspond to outgoing message IDs that expect a response
|
|
313
319
|
*/
|
|
314
|
-
acceptPostboxes = {};
|
|
320
|
+
acceptPostboxes: { [key: string]: any } = {};
|
|
315
321
|
|
|
316
322
|
// }}}
|
|
317
323
|
|
|
@@ -325,7 +331,7 @@ export default class TeraFy {
|
|
|
325
331
|
*
|
|
326
332
|
* @returns {Promise<Reactive>} A promise which resolves to the reactive object
|
|
327
333
|
*/
|
|
328
|
-
mountNamespace(name) {
|
|
334
|
+
mountNamespace(name: any) {
|
|
329
335
|
if (!/^[\w-]+$/.test(name)) throw new Error('Namespaces must be alphanumeric + hyphens + underscores');
|
|
330
336
|
if (this.namespaces[name]) return Promise.resolve(this.namespaces[name]); // Already mounted
|
|
331
337
|
|
|
@@ -343,7 +349,7 @@ export default class TeraFy {
|
|
|
343
349
|
*
|
|
344
350
|
* @returns {Promise} A promise which resolves when the mount operation has completed
|
|
345
351
|
*/
|
|
346
|
-
_mountNamespace(name) { // eslint-disable-line no-unused-vars
|
|
352
|
+
_mountNamespace(name: any) { // eslint-disable-line no-unused-vars
|
|
347
353
|
console.warn('teraFy._mountNamespace() has not been overriden by a TERA-fy plugin, load one to add this functionality for your preferred framework');
|
|
348
354
|
throw new Error('teraFy._mountNamespace() is not supported');
|
|
349
355
|
}
|
|
@@ -359,7 +365,7 @@ export default class TeraFy {
|
|
|
359
365
|
*
|
|
360
366
|
* @returns {Promise} A promise which resolves when the operation has completed
|
|
361
367
|
*/
|
|
362
|
-
unmountNamespace(name) {
|
|
368
|
+
unmountNamespace(name: any) {
|
|
363
369
|
if (!this.namespaces[name]) return Promise.resolve(); // Already unmounted
|
|
364
370
|
return this._unmountNamespace(name);
|
|
365
371
|
}
|
|
@@ -373,7 +379,7 @@ export default class TeraFy {
|
|
|
373
379
|
*
|
|
374
380
|
* @returns {Promise} A promise which resolves when the operation has completed
|
|
375
381
|
*/
|
|
376
|
-
_unmountNamespace(name) { // eslint-disable-line no-unused-vars
|
|
382
|
+
_unmountNamespace(name: any) { // eslint-disable-line no-unused-vars
|
|
377
383
|
console.warn('teraFy.unbindNamespace() has not been overriden by a TERA-fy plugin, load one to add this functionality for your preferred framework');
|
|
378
384
|
}
|
|
379
385
|
// }}}
|
|
@@ -385,10 +391,11 @@ export default class TeraFy {
|
|
|
385
391
|
*
|
|
386
392
|
* @param {Object} [options] Additional options to merge into `settings` via `set`
|
|
387
393
|
*/
|
|
388
|
-
constructor(options) {
|
|
394
|
+
constructor(options?: any) {
|
|
389
395
|
if (options) this.set(options);
|
|
390
396
|
}
|
|
391
397
|
|
|
398
|
+
private initPromise: Promise<TeraFy> | null = null;
|
|
392
399
|
|
|
393
400
|
/**
|
|
394
401
|
* Initalize the TERA client singleton
|
|
@@ -397,26 +404,27 @@ export default class TeraFy {
|
|
|
397
404
|
* @param {Object} [options] Additional options to merge into `settings` via `set`
|
|
398
405
|
* @returns {Promise<TeraFy>} An eventual promise which will resovle with this terafy instance
|
|
399
406
|
*/
|
|
400
|
-
init(options) {
|
|
407
|
+
init(options?: any): Promise<TeraFy> {
|
|
401
408
|
if (options) this.set(options);
|
|
402
|
-
if (this.
|
|
409
|
+
if (this.initPromise) return this.initPromise; // Aleady been called - return init promise
|
|
403
410
|
|
|
404
411
|
window.addEventListener('message', this.acceptMessage.bind(this));
|
|
405
412
|
|
|
406
413
|
const context = this;
|
|
407
|
-
|
|
414
|
+
this.initPromise = Promise.resolve()
|
|
408
415
|
.then(()=> this.settings.session ||= 'tfy-' + this.getEntropicString(16))
|
|
409
416
|
.then(()=> this.debug('INFO', 4, '[0/6] Init', 'Session', this.settings.session, 'against', this.settings.siteUrl))
|
|
410
417
|
.then(()=> { // Init various options for optimized access
|
|
411
418
|
if (!this.settings.devMode) return; // Not in dev mode
|
|
412
|
-
this.settings.debugPaths
|
|
413
|
-
|
|
414
|
-
: Array.isArray(this.settings.debugPaths) ? this.settings.debugPaths.map(path =>
|
|
419
|
+
if (this.settings.debugPaths) {
|
|
420
|
+
this.settings.debugPaths = (this.settings.debugPaths as any[]).map((path: any) =>
|
|
415
421
|
Array.isArray(path) ? path.join('.') // Transform arrays into dotted notation
|
|
416
422
|
: typeof path == 'string' ? path // Assume already in dotted notation
|
|
417
423
|
: (()=> { throw new Error('Unknown path type - should be an array or string in dotted notation') })()
|
|
418
424
|
)
|
|
419
|
-
|
|
425
|
+
} else {
|
|
426
|
+
this.settings.debugPaths = null;
|
|
427
|
+
}
|
|
420
428
|
|
|
421
429
|
this.debug('INFO', 0, 'Watching state paths', this.settings.debugPaths);
|
|
422
430
|
})
|
|
@@ -459,12 +467,16 @@ export default class TeraFy {
|
|
|
459
467
|
plugin.init.call(context, this.settings)
|
|
460
468
|
)
|
|
461
469
|
))
|
|
462
|
-
.then(()=>
|
|
463
|
-
|
|
470
|
+
.then(()=> {
|
|
471
|
+
this.debug('INFO', 4, '[6/6] Init complete');
|
|
472
|
+
return context; // Resolve with the instance
|
|
473
|
+
})
|
|
464
474
|
.catch(e => {
|
|
465
475
|
this.debug('WARN', 0, 'Init process fault', e);
|
|
466
|
-
|
|
467
|
-
})
|
|
476
|
+
throw e; // Re-throw
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
return this.initPromise;
|
|
468
480
|
}
|
|
469
481
|
|
|
470
482
|
|
|
@@ -475,23 +487,24 @@ export default class TeraFy {
|
|
|
475
487
|
*
|
|
476
488
|
* @returns {Promise<String>} A promise which will resolve with the detected mode to use
|
|
477
489
|
*/
|
|
478
|
-
detectMode() {
|
|
490
|
+
detectMode(): Promise<'parent' | 'child' | 'popup'> {
|
|
479
491
|
if (this.settings.mode != 'detect') { // Dev has specified a forced mode to use
|
|
480
492
|
return Promise.resolve(this.settings.mode);
|
|
481
493
|
} else if (window.self === window.parent) { // This frame is already at the top
|
|
482
|
-
return Promise.resolve(this.settings.modeFallback);
|
|
494
|
+
return Promise.resolve(this.settings.modeFallback as 'child' | 'popup');
|
|
483
495
|
} else { // No idea - try messaging
|
|
484
496
|
return Promise.resolve()
|
|
485
497
|
.then(()=> this.settings.mode = 'parent') // Switch to parent mode...
|
|
486
|
-
.then(()=> new Promise((resolve, reject) => { // And try messaging with a timeout
|
|
498
|
+
.then(()=> new Promise<void>((resolve, reject) => { // And try messaging with a timeout
|
|
487
499
|
let timeoutHandle = setTimeout(()=> reject('TIMEOUT'), this.settings.modeTimeout);
|
|
488
500
|
|
|
489
501
|
this.rpc('handshake')
|
|
490
502
|
.then(()=> clearTimeout(timeoutHandle))
|
|
491
|
-
.then(()=> resolve())
|
|
503
|
+
.then(()=> resolve(undefined))
|
|
504
|
+
.catch(reject); // Propagate RPC errors
|
|
492
505
|
}))
|
|
493
|
-
.then(()=> 'parent')
|
|
494
|
-
.catch(()=> this.settings.modeFallback)
|
|
506
|
+
.then(()=> 'parent' as 'parent')
|
|
507
|
+
.catch(()=> this.settings.modeFallback as 'child' | 'popup')
|
|
495
508
|
}
|
|
496
509
|
}
|
|
497
510
|
|
|
@@ -504,29 +517,29 @@ export default class TeraFy {
|
|
|
504
517
|
injectComms() {
|
|
505
518
|
switch (this.settings.mode) {
|
|
506
519
|
case 'child': return Promise.resolve()
|
|
507
|
-
.then(()=> new Promise(resolve => {
|
|
520
|
+
.then(()=> new Promise<void>(resolve => {
|
|
508
521
|
this.debug('INFO', 2, 'Injecting TERA site as iFrame child');
|
|
509
522
|
|
|
510
523
|
this.dom.el = document.createElement('div')
|
|
511
524
|
this.dom.el.id = 'tera-fy';
|
|
512
|
-
this.dom.el
|
|
513
|
-
this.dom.el
|
|
514
|
-
document.body.append(this.dom.el);
|
|
525
|
+
this.dom.el!.classList.toggle('dev-mode', this.settings.devMode);
|
|
526
|
+
this.dom.el!.classList.add('minimized');
|
|
527
|
+
document.body.append(this.dom.el!);
|
|
515
528
|
|
|
516
|
-
this.dom.el
|
|
529
|
+
this.dom.el!.addEventListener('click', ()=> this.dom.el!.classList.toggle('minimized'));
|
|
517
530
|
|
|
518
531
|
this.dom.iframe = document.createElement('iframe')
|
|
519
532
|
|
|
520
533
|
// Queue up event chain when document loads
|
|
521
|
-
this.dom.iframe
|
|
522
|
-
this.dom.iframe
|
|
534
|
+
this.dom.iframe!.setAttribute('sandbox', this.settings.frameSandbox.join(' '));
|
|
535
|
+
this.dom.iframe!.addEventListener('load', ()=> {
|
|
523
536
|
this.debug('INFO', 3, 'Embeded iframe ready');
|
|
524
|
-
resolve();
|
|
537
|
+
resolve(undefined);
|
|
525
538
|
});
|
|
526
539
|
|
|
527
540
|
// Start document load sequence + append to DOM
|
|
528
|
-
this.dom.iframe
|
|
529
|
-
this.dom.el
|
|
541
|
+
this.dom.iframe!.src = this.settings.siteUrl;
|
|
542
|
+
this.dom.el!.append(this.dom.iframe!);
|
|
530
543
|
}))
|
|
531
544
|
.then(()=> this.handshakeLoop())
|
|
532
545
|
|
|
@@ -556,7 +569,7 @@ export default class TeraFy {
|
|
|
556
569
|
*
|
|
557
570
|
* @returns {Promise} A promise which will either resolve when the handshake is successful OR fail with 'TIMEOUT'
|
|
558
571
|
*/
|
|
559
|
-
handshakeLoop(options) {
|
|
572
|
+
handshakeLoop(options?: any) {
|
|
560
573
|
let settings = {
|
|
561
574
|
handshakeInterval: this.settings.handshakeInterval,
|
|
562
575
|
handshakeTimeout: this.settings.handshakeTimeout,
|
|
@@ -564,9 +577,9 @@ export default class TeraFy {
|
|
|
564
577
|
};
|
|
565
578
|
|
|
566
579
|
// Loop until the window context returns a handshake
|
|
567
|
-
return new Promise((resolve, reject) => {
|
|
580
|
+
return new Promise<void>((resolve, reject) => {
|
|
568
581
|
let handshakeCount = 0;
|
|
569
|
-
let handshakeTimer;
|
|
582
|
+
let handshakeTimer: any;
|
|
570
583
|
|
|
571
584
|
let handshakeTimeout = setTimeout(()=> {
|
|
572
585
|
clearTimeout(handshakeTimer);
|
|
@@ -584,8 +597,8 @@ export default class TeraFy {
|
|
|
584
597
|
clearTimeout(handshakeTimeout);
|
|
585
598
|
clearTimeout(handshakeTimer);
|
|
586
599
|
})
|
|
587
|
-
.then(()=> resolve())
|
|
588
|
-
.catch(reject)
|
|
600
|
+
.then(()=> resolve(undefined))
|
|
601
|
+
.catch(reject) // Let RPC errors propagate
|
|
589
602
|
};
|
|
590
603
|
tryHandshake(); // Kick off initial handshake
|
|
591
604
|
});
|
|
@@ -601,7 +614,7 @@ export default class TeraFy {
|
|
|
601
614
|
switch (this.settings.mode) {
|
|
602
615
|
case 'child':
|
|
603
616
|
this.dom.stylesheet = document.createElement('style');
|
|
604
|
-
this.dom.stylesheet
|
|
617
|
+
this.dom.stylesheet!.innerHTML = [
|
|
605
618
|
':root {',
|
|
606
619
|
'--TERA-accent: #4d659c;',
|
|
607
620
|
'}',
|
|
@@ -714,7 +727,7 @@ export default class TeraFy {
|
|
|
714
727
|
'}',
|
|
715
728
|
// }}}
|
|
716
729
|
].join('\n');
|
|
717
|
-
document.head.appendChild(this.dom.stylesheet);
|
|
730
|
+
document.head.appendChild(this.dom.stylesheet!);
|
|
718
731
|
break;
|
|
719
732
|
case 'parent':
|
|
720
733
|
case 'popup':
|
|
@@ -732,7 +745,7 @@ export default class TeraFy {
|
|
|
732
745
|
*/
|
|
733
746
|
injectMethods() {
|
|
734
747
|
this.methods.forEach(method =>
|
|
735
|
-
this[method] = this.rpc.bind(this, method)
|
|
748
|
+
(this as any)[method] = this.rpc.bind(this, method)
|
|
736
749
|
);
|
|
737
750
|
}
|
|
738
751
|
// }}}
|
|
@@ -748,7 +761,7 @@ export default class TeraFy {
|
|
|
748
761
|
* @param {Number} [verboseLevel=1] The verbosity level to trigger at. If `settings.verbosity` is lower than this, the message is ignored
|
|
749
762
|
* @param {...*} [msg] Output to show
|
|
750
763
|
*/
|
|
751
|
-
debug(...msg) {
|
|
764
|
+
debug(...msg: any[]) {
|
|
752
765
|
if (!this.settings.devMode || this.settings.verbosity < 1) return; // Debugging is disabled
|
|
753
766
|
let method = 'log';
|
|
754
767
|
let verboseLevel = 1;
|
|
@@ -765,7 +778,7 @@ export default class TeraFy {
|
|
|
765
778
|
|
|
766
779
|
if (this.settings.verbosity < verboseLevel) return; // Called but this output is too verbose for our settings - skip
|
|
767
780
|
|
|
768
|
-
console[method](
|
|
781
|
+
(console as any)[method](
|
|
769
782
|
'%c[TERA-FY CLIENT]',
|
|
770
783
|
'font-weight: bold; color: #ff5722;',
|
|
771
784
|
...msg,
|
|
@@ -786,7 +799,7 @@ export default class TeraFy {
|
|
|
786
799
|
*
|
|
787
800
|
* @returns {TeraFy} This chainable terafy instance
|
|
788
801
|
*/
|
|
789
|
-
set(key, value, options) {
|
|
802
|
+
set(key: string | object, value?: any, options?: { ignoreNullish?: boolean }) {
|
|
790
803
|
let settings = {
|
|
791
804
|
ignoreNullish: true,
|
|
792
805
|
...options,
|
|
@@ -794,12 +807,12 @@ export default class TeraFy {
|
|
|
794
807
|
|
|
795
808
|
if (typeof key == 'string') {
|
|
796
809
|
if (!settings.ignoreNullish || (value !== null && value !== undefined))
|
|
797
|
-
this.settings[key] = value;
|
|
810
|
+
(this.settings as any)[key] = value;
|
|
798
811
|
} else {
|
|
799
812
|
Object.assign(this.settings, key);
|
|
800
813
|
}
|
|
801
814
|
|
|
802
|
-
return this.toggleDevMode(this.settings.devMode);
|
|
815
|
+
return this.toggleDevMode(this.settings.devMode as boolean);
|
|
803
816
|
}
|
|
804
817
|
|
|
805
818
|
|
|
@@ -813,7 +826,7 @@ export default class TeraFy {
|
|
|
813
826
|
*
|
|
814
827
|
* @returns {TeraFy} This chainable terafy instance
|
|
815
828
|
*/
|
|
816
|
-
setIfDev(key, value, options) {
|
|
829
|
+
setIfDev(key: any, value: any, options?: any) {
|
|
817
830
|
if (!this.settings.devMode || value === undefined) return this;
|
|
818
831
|
return this.set(key, value, options);
|
|
819
832
|
}
|
|
@@ -827,8 +840,8 @@ export default class TeraFy {
|
|
|
827
840
|
*
|
|
828
841
|
* @returns {TeraFy} This chainable terafy instance
|
|
829
842
|
*/
|
|
830
|
-
use(source, options) {
|
|
831
|
-
let mod =
|
|
843
|
+
use(source: any, options?: any) {
|
|
844
|
+
let mod: any =
|
|
832
845
|
typeof source == 'function' ? new source(this, options)
|
|
833
846
|
: typeof source == 'object' ? source
|
|
834
847
|
: typeof source == 'string' ? (()=> { throw new Error('use(String) is not yet supported') })()
|
|
@@ -847,7 +860,7 @@ export default class TeraFy {
|
|
|
847
860
|
* @param {Object} target Initalied class instance to extend
|
|
848
861
|
* @param {Object} source Initalized source object to extend from
|
|
849
862
|
*/
|
|
850
|
-
mixin(target, source) {
|
|
863
|
+
mixin(target: any, source: any) {
|
|
851
864
|
// Iterate through the source object upwards extracting each prototype
|
|
852
865
|
let prototypeStack = [];
|
|
853
866
|
let node = source;
|
|
@@ -863,17 +876,17 @@ export default class TeraFy {
|
|
|
863
876
|
&& !prop.startsWith('__') // Ignore double underscore meta properties
|
|
864
877
|
)
|
|
865
878
|
.forEach(prop => {
|
|
866
|
-
if (typeof source[prop] == 'function') { // Inheriting function - glue onto object as non-editable, non-enumerable property
|
|
879
|
+
if (typeof (source as any)[prop] == 'function') { // Inheriting function - glue onto object as non-editable, non-enumerable property
|
|
867
880
|
Object.defineProperty(
|
|
868
881
|
target,
|
|
869
882
|
prop,
|
|
870
883
|
{
|
|
871
884
|
enumerable: false,
|
|
872
|
-
value: source[prop].bind(target), // Rebind functions
|
|
885
|
+
value: (source as any)[prop].bind(target), // Rebind functions
|
|
873
886
|
},
|
|
874
887
|
);
|
|
875
888
|
} else { // Everything else, just glue onto the object
|
|
876
|
-
target[prop] = source[prop];
|
|
889
|
+
target[prop] = (source as any)[prop];
|
|
877
890
|
}
|
|
878
891
|
})
|
|
879
892
|
)
|
|
@@ -891,7 +904,7 @@ export default class TeraFy {
|
|
|
891
904
|
*
|
|
892
905
|
* @returns {TeraFy} This chainable terafy instance
|
|
893
906
|
*/
|
|
894
|
-
toggleDevMode(devModeEnabled = 'toggle') {
|
|
907
|
+
toggleDevMode(devModeEnabled: 'toggle' | 'proxy' | boolean = 'toggle') {
|
|
895
908
|
if (devModeEnabled === 'toggle') {
|
|
896
909
|
this.settings.devMode = !this.settings.devMode;
|
|
897
910
|
} else if (devModeEnabled === 'proxy') {
|
|
@@ -908,7 +921,7 @@ export default class TeraFy {
|
|
|
908
921
|
this.settings.restrictOrigin = '*'; // Allow all upstream iframes
|
|
909
922
|
|
|
910
923
|
if (this.dom?.el) // Have we actually set up yet?
|
|
911
|
-
this.dom.el
|
|
924
|
+
this.dom.el!.classList.toggle('dev-mode', this.settings.devMode);
|
|
912
925
|
|
|
913
926
|
return this;
|
|
914
927
|
}
|
|
@@ -920,7 +933,7 @@ export default class TeraFy {
|
|
|
920
933
|
*
|
|
921
934
|
* @param {String|Boolean} [isFocused='toggle'] Whether to fullscreen the embedded component
|
|
922
935
|
*/
|
|
923
|
-
toggleFocus(isFocused = 'toggle') {
|
|
936
|
+
toggleFocus(isFocused: boolean | 'toggle' = 'toggle') {
|
|
924
937
|
this.debug('INFO', 2, 'Request focus', {isFocused});
|
|
925
938
|
globalThis.document.body.classList.toggle('tera-fy-focus', isFocused === 'toggle' ? undefined : isFocused);
|
|
926
939
|
}
|
|
@@ -1187,9 +1200,9 @@ export default class TeraFy {
|
|
|
1187
1200
|
*
|
|
1188
1201
|
* @returns {Promise<ProjectFile>} The eventually selected file, if in save mode new files are created as stubs
|
|
1189
1202
|
*/
|
|
1190
|
-
selectProjectFile(options) {
|
|
1203
|
+
selectProjectFile(options?: any) {
|
|
1191
1204
|
return this.rpc('selectProjectFile', options)
|
|
1192
|
-
.then(file => file
|
|
1205
|
+
.then((file: any) => file
|
|
1193
1206
|
? new ProjectFile({
|
|
1194
1207
|
tera: this,
|
|
1195
1208
|
...file,
|
|
@@ -1210,9 +1223,9 @@ export default class TeraFy {
|
|
|
1210
1223
|
*
|
|
1211
1224
|
* @returns {Promise<Array<ProjectFile>>} A collection of project files for the given project
|
|
1212
1225
|
*/
|
|
1213
|
-
getProjectFiles(options) {
|
|
1226
|
+
getProjectFiles(options?: any) {
|
|
1214
1227
|
return this.rpc('getProjectFiles', options)
|
|
1215
|
-
.then(files => files.map(file =>
|
|
1228
|
+
.then((files: any) => files.map((file: any) =>
|
|
1216
1229
|
new ProjectFile({
|
|
1217
1230
|
tera: this,
|
|
1218
1231
|
...file,
|
|
@@ -1245,9 +1258,9 @@ export default class TeraFy {
|
|
|
1245
1258
|
*
|
|
1246
1259
|
* @returns {Promise<ProjectFile>} The eventual fetched ProjectFile (or requested subkey)
|
|
1247
1260
|
*/
|
|
1248
|
-
getProjectFile(id, options) {
|
|
1261
|
+
getProjectFile(id: any, options?: any) {
|
|
1249
1262
|
return this.rpc('getProjectFile', id, options)
|
|
1250
|
-
.then(file => file
|
|
1263
|
+
.then((file: any) => file
|
|
1251
1264
|
? new ProjectFile({
|
|
1252
1265
|
tera: this,
|
|
1253
1266
|
...file,
|
|
@@ -1265,9 +1278,9 @@ export default class TeraFy {
|
|
|
1265
1278
|
* @param {String} name The name + relative directory path component
|
|
1266
1279
|
* @returns {Promise<ProjectFile>} The eventual ProjectFile created
|
|
1267
1280
|
*/
|
|
1268
|
-
createProjectFile(name) {
|
|
1281
|
+
createProjectFile(name: any) {
|
|
1269
1282
|
return this.rpc('createProjectFile', name)
|
|
1270
|
-
.then(file => file
|
|
1283
|
+
.then((file: any) => file
|
|
1271
1284
|
? new ProjectFile({
|
|
1272
1285
|
tera: this,
|
|
1273
1286
|
...file,
|
|
@@ -1276,6 +1289,36 @@ export default class TeraFy {
|
|
|
1276
1289
|
)
|
|
1277
1290
|
}
|
|
1278
1291
|
|
|
1292
|
+
/**
|
|
1293
|
+
* Moves a project file to a new name/path.
|
|
1294
|
+
* The file's unique ID (UUID) remains the same, but its 'name' (relative path) and associated properties will be updated.
|
|
1295
|
+
*
|
|
1296
|
+
* @function moveProjectFile
|
|
1297
|
+
* @param {String} sourceId The unique ID (UUID) of the file to move.
|
|
1298
|
+
* @param {String} newName The new relative name for the file (e.g., "documents/report-final.pdf" or "image.png").
|
|
1299
|
+
* This path is relative to the project's root file directory.
|
|
1300
|
+
*
|
|
1301
|
+
* @param {Object} [options] Additional options to mutate behaviour.
|
|
1302
|
+
* @param {Boolean} [options.autoRequire=true] Run `requireProject()` automatically before continuing.
|
|
1303
|
+
* @param {Boolean} [options.overwrite=true] If true (default), moving a file to a `newName` that already exists will overwrite the existing file.
|
|
1304
|
+
* This aligns with the default behavior of the underlying Supabase storage `move` operation.
|
|
1305
|
+
* If set to false, the function would ideally check and prevent overwrite, but current implementation relies on underlying storage behavior.
|
|
1306
|
+
*
|
|
1307
|
+
* @returns {Promise<ProjectFile | null>} A promise which resolves to the updated ProjectFile object for the moved file if found after the operation,
|
|
1308
|
+
* or null if the file could not be located post-move (e.g., if its ID changed unexpectedly or it was deleted).
|
|
1309
|
+
*/
|
|
1310
|
+
moveProjectFile(sourceId: string, newName: string, options?: any): Promise<ProjectFile | null> {
|
|
1311
|
+
return this.rpc('moveProjectFile', sourceId, newName, options)
|
|
1312
|
+
.then((fileData: any) => { // fileData is the plain object from the server
|
|
1313
|
+
if (fileData) {
|
|
1314
|
+
return new ProjectFile({
|
|
1315
|
+
tera: this, // Pass the TeraFy client instance
|
|
1316
|
+
...fileData,
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
return null;
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1279
1322
|
|
|
1280
1323
|
/**
|
|
1281
1324
|
* Remove a project file by its ID
|
|
@@ -1304,6 +1347,30 @@ export default class TeraFy {
|
|
|
1304
1347
|
* @returns {Promise} A promise which will resolve when the write operation has completed
|
|
1305
1348
|
*/
|
|
1306
1349
|
|
|
1350
|
+
/**
|
|
1351
|
+
* Creates a new "folder" within the project's file storage.
|
|
1352
|
+
* Folders in Supabase storage are typically represented by creating a placeholder file (e.g., .emptyFolderPlaceholder) within the desired path.
|
|
1353
|
+
* This operation is idempotent: if the folder (via its placeholder) already exists, it will not error.
|
|
1354
|
+
*
|
|
1355
|
+
* @function createProjectFolder
|
|
1356
|
+
* @param {String} folderPath The relative path of the folder to create (e.g., "myDocuments/reports").
|
|
1357
|
+
* @param {Object} [options] Additional options.
|
|
1358
|
+
* @param {Boolean} [options.autoRequire=true] Automatically run `requireProject()` to ensure an active project context.
|
|
1359
|
+
* @returns {Promise<void>} A promise that resolves when the folder is created or ensured.
|
|
1360
|
+
* @throws {Error} If no project is active (and autoRequire is false), or if folderPath is invalid, or if the creation fails.
|
|
1361
|
+
*/
|
|
1362
|
+
|
|
1363
|
+
/**
|
|
1364
|
+
* Deletes a "folder" and all its contents from the project's file storage.
|
|
1365
|
+
* This involves listing all files under the given folder path (prefix) and removing them.
|
|
1366
|
+
*
|
|
1367
|
+
* @function deleteProjectFolder
|
|
1368
|
+
* @param {String} folderPath The relative path of the folder to delete (e.g., "myDocuments/reports").
|
|
1369
|
+
* @param {Object} [options] Additional options.
|
|
1370
|
+
* @param {Boolean} [options.autoRequire=true] Automatically run `requireProject()` to ensure an active project context.
|
|
1371
|
+
* @returns {Promise<null>} A promise that resolves with null when the folder and its contents are deleted.
|
|
1372
|
+
* @throws {Error} If no project is active (and autoRequire is false), or if folderPath is invalid, or if deletion fails.
|
|
1373
|
+
*/
|
|
1307
1374
|
|
|
1308
1375
|
/**
|
|
1309
1376
|
* Prompt the user to select a library to operate on and return a array of references in a given format
|
|
@@ -1498,4 +1565,4 @@ export default class TeraFy {
|
|
|
1498
1565
|
*/
|
|
1499
1566
|
|
|
1500
1567
|
// }}}
|
|
1501
|
-
}
|
|
1568
|
+
}
|