@iebh/tera-fy 2.3.7 → 2.3.9
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 +35 -0
- package/dist/lib/projectFile.js +118 -6
- package/dist/lib/projectFile.js.map +1 -1
- package/dist/lib/syncro/entities.d.ts +7 -1
- package/dist/lib/syncro/entities.js +79 -95
- package/dist/lib/syncro/entities.js.map +1 -1
- package/dist/lib/syncro/keyed.js +24 -23
- package/dist/lib/syncro/keyed.js.map +1 -1
- package/dist/lib/syncro/syncro.d.ts +15 -2
- package/dist/lib/syncro/syncro.js +124 -43
- package/dist/lib/syncro/syncro.js.map +1 -1
- package/dist/lib/terafy.bootstrapper.js +11 -11
- package/dist/lib/terafy.bootstrapper.js.map +1 -1
- package/dist/lib/terafy.client.js +157 -158
- package/dist/lib/terafy.client.js.map +1 -1
- package/dist/lib/terafy.proxy.js +32 -27
- package/dist/lib/terafy.proxy.js.map +1 -1
- package/dist/lib/terafy.server.js +52 -54
- package/dist/lib/terafy.server.js.map +1 -1
- package/dist/plugin.vue2.es2019.js +27 -27
- package/dist/plugins/firebase.js +22 -10
- package/dist/plugins/firebase.js.map +1 -1
- package/dist/plugins/vue2.d.ts +1 -2
- package/dist/plugins/vue2.js +24 -17
- package/dist/plugins/vue2.js.map +1 -1
- package/dist/plugins/vue3.d.ts +1 -2
- package/dist/plugins/vue3.js +7 -11
- package/dist/plugins/vue3.js.map +1 -1
- 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 +1 -1
- package/lib/syncro/entities.ts +94 -103
- package/lib/syncro/keyed.ts +1 -0
- package/lib/syncro/syncro.ts +44 -8
- package/lib/terafy.client.ts +0 -1
- package/lib/terafy.server.ts +6 -7
- package/package.json +4 -3
- package/plugins/vue2.ts +2 -3
- package/plugins/vue3.ts +2 -4
- package/tsconfig.json +3 -3
package/lib/syncro/syncro.ts
CHANGED
|
@@ -21,16 +21,24 @@ import {
|
|
|
21
21
|
// @ts-expect-error No declaration file for marshal
|
|
22
22
|
import marshal from '@momsfriendlydevco/marshal';
|
|
23
23
|
import {nanoid} from 'nanoid';
|
|
24
|
+
import PromiseThrottle from 'p-throttle';
|
|
24
25
|
import PromiseRetry from 'p-retry';
|
|
25
26
|
import {FirebaseApp, FirebaseError} from 'firebase/app';
|
|
26
27
|
import { BoundSupabaseyFunction } from '@iebh/supabasey';
|
|
28
|
+
import type { PostgresSql } from './entities.js';
|
|
27
29
|
|
|
30
|
+
interface ThrottleOptions<T = any> {
|
|
31
|
+
limit: number,
|
|
32
|
+
interval: number,
|
|
33
|
+
strict: boolean,
|
|
34
|
+
}
|
|
28
35
|
|
|
29
36
|
interface ReactiveWrapper<T = any> {
|
|
30
37
|
doc: T;
|
|
31
38
|
setState: (newState: T) => void;
|
|
32
39
|
getState: () => T;
|
|
33
40
|
watch: (cb: (newState: T) => void) => void;
|
|
41
|
+
throttle?: ThrottleOptions | true,
|
|
34
42
|
}
|
|
35
43
|
|
|
36
44
|
interface PathSplitResult {
|
|
@@ -74,6 +82,14 @@ export default class Syncro {
|
|
|
74
82
|
static supabasey: BoundSupabaseyFunction;
|
|
75
83
|
|
|
76
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Postgres SQL instance in use (injected by the Cloudflare Worker runtime via Hyperdrive)
|
|
87
|
+
*
|
|
88
|
+
* @type {PostgresSql}
|
|
89
|
+
*/
|
|
90
|
+
static db: PostgresSql;
|
|
91
|
+
|
|
92
|
+
|
|
77
93
|
/**
|
|
78
94
|
* The current user session, should be unique for the user + browser tab
|
|
79
95
|
* Used by the heartbeat system
|
|
@@ -169,7 +185,7 @@ export default class Syncro {
|
|
|
169
185
|
* @param {*...} [msg] The message to output
|
|
170
186
|
*/
|
|
171
187
|
debugError(...msg: any[]) {
|
|
172
|
-
console.
|
|
188
|
+
console.warn(`[Syncro ${this.path}]`, ...msg);
|
|
173
189
|
}
|
|
174
190
|
|
|
175
191
|
|
|
@@ -202,9 +218,10 @@ export default class Syncro {
|
|
|
202
218
|
*/
|
|
203
219
|
destroy(): Promise<any[]> {
|
|
204
220
|
this.debug('Destroy!');
|
|
205
|
-
return Promise.
|
|
206
|
-
.
|
|
207
|
-
|
|
221
|
+
return Promise.resolve()
|
|
222
|
+
.then(()=> Promise.all(this._destroyActions // eslint-disable @typescript-eslint/await-thenable
|
|
223
|
+
.map(fn => fn())
|
|
224
|
+
))
|
|
208
225
|
.then(()=> this._destroyActions = []) // Reset list of actions to perform when terminating
|
|
209
226
|
}
|
|
210
227
|
|
|
@@ -213,7 +230,7 @@ export default class Syncro {
|
|
|
213
230
|
* Actions to preform when we are destroying this instance
|
|
214
231
|
* This is an array of function callbacks to execute in parallel when `destroy()` is called
|
|
215
232
|
*
|
|
216
|
-
* @type {Array<
|
|
233
|
+
* @type {Array<Function<Promise>>}
|
|
217
234
|
*/
|
|
218
235
|
_destroyActions: Array<() => void> = [];
|
|
219
236
|
|
|
@@ -531,6 +548,25 @@ export default class Syncro {
|
|
|
531
548
|
// Construct a reactive component
|
|
532
549
|
reactive = this.getReactive(initialState);
|
|
533
550
|
if (!reactive.doc || !reactive.setState || !reactive.getState || !reactive.watch) throw new Error('Syncro.getReactive() requires a returned `doc`, `setState()`, `getState()` + `watch()`');
|
|
551
|
+
|
|
552
|
+
// Accept throttling for reactiveWrapper if present
|
|
553
|
+
if (reactive.throttle) { // Wanting to throttle - handed either truthy or an object of throttle settings
|
|
554
|
+
let throttleSettings = {
|
|
555
|
+
limit: 2,
|
|
556
|
+
interval: 100, // i.e. 2 calls within 100ms, otherwise throttle
|
|
557
|
+
strict: false,
|
|
558
|
+
...(typeof reactive.throttle == 'object' && reactive.throttle), // Import throttle settings if any
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
// Wrap original reactive.setState() in a throttle function
|
|
562
|
+
let originalSetState = reactive.setState;
|
|
563
|
+
reactive.setState = PromiseThrottle({
|
|
564
|
+
limit: throttleSettings.limit,
|
|
565
|
+
interval: throttleSettings.interval,
|
|
566
|
+
onDelay: ()=> this.debug('Throttling excessive Syncro.setState() writes'),
|
|
567
|
+
})(originalSetState);
|
|
568
|
+
}
|
|
569
|
+
|
|
534
570
|
this.value = doc = reactive.doc;
|
|
535
571
|
|
|
536
572
|
this.debug('Initial state', {doc});
|
|
@@ -562,7 +598,7 @@ export default class Syncro {
|
|
|
562
598
|
reactive.watch(throttle((newState: any) => {
|
|
563
599
|
this.debug('Local change', {newState});
|
|
564
600
|
this.markDirty();
|
|
565
|
-
this.setFirestoreState(newState, {method: 'merge'});
|
|
601
|
+
this.setFirestoreState(newState, {method: 'merge'}); // eslint-disable-line @typescript-eslint/no-floating-promises
|
|
566
602
|
}, this.throttle));
|
|
567
603
|
|
|
568
604
|
await this.setHeartbeat(true, {
|
|
@@ -656,7 +692,7 @@ export default class Syncro {
|
|
|
656
692
|
*
|
|
657
693
|
* @param {Object} [options] Additional options to mutate behaviour
|
|
658
694
|
* @param {Boolean} [options.immediate=false] Fire a heartbeat as soon as this function is called, this is only really useful on mount
|
|
659
|
-
* @returns Promise that resolves
|
|
695
|
+
* @returns {Promise|Void} A promise that resolves when completed (if `{immediate:true}`) or void
|
|
660
696
|
*/
|
|
661
697
|
setHeartbeat(enable: boolean = true, options?: any): Promise<void> | void {
|
|
662
698
|
const settings = {
|
|
@@ -673,7 +709,7 @@ export default class Syncro {
|
|
|
673
709
|
await this.heartbeat();
|
|
674
710
|
|
|
675
711
|
// If we're enabled - schedule the next heartbeat timer
|
|
676
|
-
if (enable) this.setHeartbeat(true); //
|
|
712
|
+
if (enable) this.setHeartbeat(true); // eslint-disable-line @typescript-eslint/no-floating-promises
|
|
677
713
|
};
|
|
678
714
|
|
|
679
715
|
this._heartbeatTimer = setTimeout(heartbeatAction, this.config.heartbeatInterval);
|
package/lib/terafy.client.ts
CHANGED
|
@@ -68,7 +68,6 @@ export default class TeraFy {
|
|
|
68
68
|
* Event emitter subscription endpoint
|
|
69
69
|
* @type {Mitt}
|
|
70
70
|
*/
|
|
71
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
72
71
|
// @ts-ignore - Because mitt is exported as cjs typescript has trouble resolving default export
|
|
73
72
|
events = Mitt();
|
|
74
73
|
|
package/lib/terafy.server.ts
CHANGED
|
@@ -619,7 +619,7 @@ export default class TeraFyServer {
|
|
|
619
619
|
await app.service('$projects').refresh();
|
|
620
620
|
return;
|
|
621
621
|
} catch (e: any) {
|
|
622
|
-
throw new Error(`Failed to decode local dev state - ${e.toString()}
|
|
622
|
+
throw new Error(`Failed to decode local dev state - ${e.toString()}`, {cause: e});
|
|
623
623
|
}
|
|
624
624
|
}
|
|
625
625
|
|
|
@@ -1000,7 +1000,6 @@ export default class TeraFyServer {
|
|
|
1000
1000
|
.then(()=> pathTools.get(target, path));
|
|
1001
1001
|
} else { // Called as (value, options?) - Populate entire project layout
|
|
1002
1002
|
actualValue = path; // The first argument is the value
|
|
1003
|
-
settings = { ...value }; // The second argument holds the options
|
|
1004
1003
|
pathTools.defaults(target, actualValue);
|
|
1005
1004
|
this.debug('INFO', 1, 'setProjectStateDefaults', {
|
|
1006
1005
|
defaults: actualValue,
|
|
@@ -1360,7 +1359,7 @@ export default class TeraFyServer {
|
|
|
1360
1359
|
} catch (error: any) {
|
|
1361
1360
|
this.debug('ERROR', 1, `Error during project file move from "${sourceStoragePath}" to "${targetStoragePath}":`, error);
|
|
1362
1361
|
// Re-throw a more specific error or the original error for the caller to handle.
|
|
1363
|
-
throw new Error(`Failed to move project file "${sourceId}" to "${newName}": ${error.message || String(error)}
|
|
1362
|
+
throw new Error(`Failed to move project file "${sourceId}" to "${newName}": ${error.message || String(error)}`, {cause: error});
|
|
1364
1363
|
}
|
|
1365
1364
|
}
|
|
1366
1365
|
|
|
@@ -1397,7 +1396,7 @@ export default class TeraFyServer {
|
|
|
1397
1396
|
*/
|
|
1398
1397
|
setProjectFileContents(id: string | any | null, contents: any, options?: any): Promise<null> {
|
|
1399
1398
|
// Argument Mangling Logic (Simplified)
|
|
1400
|
-
let fileId: string | null = null;
|
|
1399
|
+
let fileId: string | null = null; // eslint-disable-line no-useless-assignment
|
|
1401
1400
|
let fileContents: any;
|
|
1402
1401
|
let mergedOptions: any;
|
|
1403
1402
|
|
|
@@ -1527,7 +1526,7 @@ export default class TeraFyServer {
|
|
|
1527
1526
|
this.debug('INFO', 2, `Project folder "${cleanFolderPath}" ensured/created via placeholder at "${relativePlaceholderPath}".`);
|
|
1528
1527
|
} catch (error: any) {
|
|
1529
1528
|
this.debug('ERROR', 1, `Failed to create/ensure project folder "${cleanFolderPath}" via placeholder "${relativePlaceholderPath}"`, error);
|
|
1530
|
-
throw new Error(`Failed to create project folder "${cleanFolderPath}": ${error.message || String(error)}
|
|
1529
|
+
throw new Error(`Failed to create project folder "${cleanFolderPath}": ${error.message || String(error)}`, {cause: error});
|
|
1531
1530
|
}
|
|
1532
1531
|
}
|
|
1533
1532
|
|
|
@@ -1602,7 +1601,7 @@ export default class TeraFyServer {
|
|
|
1602
1601
|
this.debug('INFO', 2, `Project folder "${cleanFolderPath}" (prefix "${pathPrefix}") and its ${filesToDelete.length} contents deleted.`);
|
|
1603
1602
|
} catch (error: any) {
|
|
1604
1603
|
this.debug('ERROR', 1, `Failed to delete contents of project folder "${cleanFolderPath}" (prefix "${pathPrefix}")`, error);
|
|
1605
|
-
throw new Error(`Failed to delete project folder "${cleanFolderPath}": ${error.message || String(error)}
|
|
1604
|
+
throw new Error(`Failed to delete project folder "${cleanFolderPath}": ${error.message || String(error)}`, {cause: error});
|
|
1606
1605
|
}
|
|
1607
1606
|
return null;
|
|
1608
1607
|
}
|
|
@@ -1728,7 +1727,7 @@ export default class TeraFyServer {
|
|
|
1728
1727
|
*/
|
|
1729
1728
|
setProjectLibrary(id: string | any | null, refs?: any, options?: any): Promise<null> {
|
|
1730
1729
|
// Argument Mangling Logic (Simplified)
|
|
1731
|
-
let fileId: string | null = null;
|
|
1730
|
+
let fileId: string | null = null; // eslint-disable-line no-useless-assignment
|
|
1732
1731
|
let libraryRefs: any;
|
|
1733
1732
|
let mergedOptions: any;
|
|
1734
1733
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iebh/tera-fy",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.9",
|
|
4
4
|
"description": "TERA website worker",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "esbuild --platform=browser --format=esm --bundle lib/terafy.client.ts --outfile=dist/terafy.js --minify --serve --servedir=.",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"build:docs:markdown": "documentation build lib/terafy.client.ts lib/projectFile.ts --format md --markdown-toc --output api.md",
|
|
16
16
|
"lint": "eslint",
|
|
17
17
|
"release": "release-it",
|
|
18
|
-
"watch": "nodemon --watch lib --watch plugins --exec \"npm run build\""
|
|
18
|
+
"watch": "nodemon --watch lib --watch plugins --ext ts --exec \"npm run build\""
|
|
19
19
|
},
|
|
20
20
|
"type": "module",
|
|
21
21
|
"imports": {
|
|
@@ -113,11 +113,12 @@
|
|
|
113
113
|
"mitt": "^3.0.1",
|
|
114
114
|
"nanoid": "^5.1.6",
|
|
115
115
|
"p-retry": "^7.1.1",
|
|
116
|
+
"p-throttle": "^8.1.0",
|
|
116
117
|
"release-it": "^19.2.4",
|
|
117
118
|
"uuid": "^13.0.0"
|
|
118
119
|
},
|
|
119
120
|
"devDependencies": {
|
|
120
|
-
"@momsfriendlydevco/eslint-config": "^2.4.
|
|
121
|
+
"@momsfriendlydevco/eslint-config": "^2.4.2",
|
|
121
122
|
"@release-it/conventional-changelog": "^10.0.5",
|
|
122
123
|
"@types/detect-port": "^2.0.0",
|
|
123
124
|
"@types/http-proxy": "^1.17.17",
|
package/plugins/vue2.ts
CHANGED
|
@@ -59,11 +59,10 @@ export default class TeraFyPluginVue2 extends TeraFyPluginFirebase {
|
|
|
59
59
|
/**
|
|
60
60
|
* Install into Vue@2
|
|
61
61
|
*
|
|
62
|
-
* @param {Object} options Additional options to mutate behaviour, see TeraFyPluginFirebase
|
|
62
|
+
* @param {Object} options Additional options to mutate behaviour, see TeraFyPluginFirebase for additional options
|
|
63
63
|
* @param {Object} options.app Root level Vue app to bind against
|
|
64
64
|
* @param {Vue} options.Vue Vue@2 instance to bind against
|
|
65
65
|
* @param {String} [options.globalName='$tera'] Global property to allocate this service as within Vue2
|
|
66
|
-
* @param {*...} [options...] see TeraFyPluginFirebase
|
|
67
66
|
*
|
|
68
67
|
* @returns {Promise} A Promise which will resolve when the init process has completed
|
|
69
68
|
*/
|
|
@@ -117,4 +116,4 @@ export default class TeraFyPluginVue2 extends TeraFyPluginFirebase {
|
|
|
117
116
|
};
|
|
118
117
|
}
|
|
119
118
|
|
|
120
|
-
}
|
|
119
|
+
}
|
package/plugins/vue3.ts
CHANGED
|
@@ -39,8 +39,7 @@ export default class TeraFyPluginVue3 extends TeraFyPluginFirebase {
|
|
|
39
39
|
/**
|
|
40
40
|
* Init the project including create a reactive mount for the active project
|
|
41
41
|
*
|
|
42
|
-
* @param {Object} options Additional options to mutate behaviour
|
|
43
|
-
* @param {*} [options...] see TeraFyPluginFirebase
|
|
42
|
+
* @param {Object} options Additional options to mutate behaviour, see TeraFyPluginFirebase
|
|
44
43
|
*/
|
|
45
44
|
async init(options: Record<string, any>) {
|
|
46
45
|
await super.init(options); // Initalize parent class Firebase functionality
|
|
@@ -103,5 +102,4 @@ export default class TeraFyPluginVue3 extends TeraFyPluginFirebase {
|
|
|
103
102
|
|
|
104
103
|
};
|
|
105
104
|
}
|
|
106
|
-
|
|
107
|
-
}
|
|
105
|
+
}
|
package/tsconfig.json
CHANGED