@dittolive/ditto 4.4.1 → 4.4.2-alpha1
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 +2 -2
- package/node/ditto.cjs.js +312 -75
- package/node/ditto.darwin-arm64.node +0 -0
- package/node/ditto.darwin-x64.node +0 -0
- package/node/ditto.linux-arm.node +0 -0
- package/node/ditto.linux-x64.node +0 -0
- package/node/ditto.win32-x64.node +0 -0
- package/node/transports.darwin-arm64.node +0 -0
- package/node/transports.darwin-x64.node +0 -0
- package/package.json +1 -1
- package/types/ditto.d.ts +137 -40
- package/web/ditto.es6.js +1 -1
- package/web/ditto.umd.js +1 -1
- package/web/ditto.wasm +0 -0
package/node/ditto.cjs.js
CHANGED
|
@@ -70,10 +70,14 @@ KeepAlive.finalizationRegistry = new FinalizationRegistry(clearInterval);
|
|
|
70
70
|
* alive, you have to keep a reference to the corresponding observer.
|
|
71
71
|
*/
|
|
72
72
|
class Observer {
|
|
73
|
+
/** @internal */
|
|
74
|
+
get token() {
|
|
75
|
+
return this._token;
|
|
76
|
+
}
|
|
73
77
|
/** @internal */
|
|
74
78
|
constructor(observerManager, token, options = {}) {
|
|
75
79
|
this.observerManager = observerManager;
|
|
76
|
-
this.
|
|
80
|
+
this._token = token;
|
|
77
81
|
this.options = options;
|
|
78
82
|
if (options.stopsWhenFinalized) {
|
|
79
83
|
Observer.finalizationRegistry.register(this, { observerManager, token }, this);
|
|
@@ -84,7 +88,7 @@ class Observer {
|
|
|
84
88
|
* method. Otherwise returns `false`.
|
|
85
89
|
*/
|
|
86
90
|
get isStopped() {
|
|
87
|
-
return this.observerManager.hasObserver(this.token);
|
|
91
|
+
return this.token !== undefined && this.observerManager.hasObserver(this.token);
|
|
88
92
|
}
|
|
89
93
|
/**
|
|
90
94
|
* Stops the observation. Calling this method multiple times has no effect.
|
|
@@ -92,7 +96,7 @@ class Observer {
|
|
|
92
96
|
stop() {
|
|
93
97
|
const token = this.token;
|
|
94
98
|
if (token) {
|
|
95
|
-
delete this
|
|
99
|
+
delete this._token;
|
|
96
100
|
Observer.finalizationRegistry.unregister(this);
|
|
97
101
|
this.observerManager.removeObserver(token);
|
|
98
102
|
}
|
|
@@ -121,24 +125,29 @@ class Value {
|
|
|
121
125
|
// NOTE: we use a token to detect private invocation of the constructor. This is
|
|
122
126
|
// not secure and just to prevent accidental private invocation on the client
|
|
123
127
|
// side.
|
|
124
|
-
const privateToken$1 = '
|
|
128
|
+
const privateToken$1 = Symbol('privateConstructorToken');
|
|
125
129
|
/**
|
|
126
130
|
* Represents a CRDT counter that can be upserted as part of a document or
|
|
127
131
|
* assigned to a property during an update of a document.
|
|
128
132
|
*/
|
|
129
133
|
class Counter {
|
|
134
|
+
/** The value of the counter. */
|
|
135
|
+
get value() {
|
|
136
|
+
return this._value;
|
|
137
|
+
}
|
|
130
138
|
/**
|
|
131
139
|
* Creates a new counter that can be used as part of a document's content.
|
|
132
140
|
*/
|
|
133
141
|
constructor() {
|
|
134
|
-
this.
|
|
142
|
+
this._value = 0.0;
|
|
135
143
|
}
|
|
136
144
|
/** @internal */
|
|
137
145
|
static '@ditto.create'(mutDoc, path, value) {
|
|
146
|
+
// @ts-expect-error - using hidden argument
|
|
138
147
|
const counter = mutDoc ? new MutableCounter(privateToken$1) : new Counter();
|
|
139
148
|
counter.mutDoc = mutDoc;
|
|
140
149
|
counter.path = path;
|
|
141
|
-
counter
|
|
150
|
+
counter._value = value;
|
|
142
151
|
return counter;
|
|
143
152
|
}
|
|
144
153
|
}
|
|
@@ -160,15 +169,15 @@ class MutableCounter extends Counter {
|
|
|
160
169
|
* otherwise an exception is thrown.
|
|
161
170
|
*/
|
|
162
171
|
increment(amount) {
|
|
163
|
-
const mutDoc = this
|
|
164
|
-
const path = this
|
|
172
|
+
const mutDoc = this.mutDoc;
|
|
173
|
+
const path = this.path;
|
|
165
174
|
if (!mutDoc) {
|
|
166
175
|
throw new Error(`Can't increment counter, only possible within the closure of a collection's update() method.`);
|
|
167
176
|
}
|
|
168
177
|
mutDoc.at(path)['@ditto.increment'](amount);
|
|
169
178
|
// We also increment the local value to make sure that the change is
|
|
170
179
|
// reflected locally as well as in the underlying document
|
|
171
|
-
this
|
|
180
|
+
this._value += amount;
|
|
172
181
|
}
|
|
173
182
|
/** @internal */
|
|
174
183
|
constructor() {
|
|
@@ -324,9 +333,11 @@ function ditto_document_set_cbor(...args) { return ditto.ditto_document_set_cbor
|
|
|
324
333
|
function ditto_document_set_cbor_with_timestamp(...args) { return ditto.ditto_document_set_cbor_with_timestamp(...args) }
|
|
325
334
|
function ditto_documents_hash(...args) { return ditto.ditto_documents_hash(...args) }
|
|
326
335
|
function ditto_documents_hash_mnemonic(...args) { return ditto.ditto_documents_hash_mnemonic(...args) }
|
|
336
|
+
function ditto_dql_response_free(...args) { return ditto.ditto_dql_response_free(...args) }
|
|
337
|
+
function ditto_dql_response_results(...args) { return ditto.ditto_dql_response_results(...args) }
|
|
338
|
+
function ditto_dql_result_free(...args) { return ditto.ditto_dql_result_free(...args) }
|
|
327
339
|
function ditto_error_message(...args) { return ditto.ditto_error_message(...args) }
|
|
328
340
|
function ditto_experimental_add_dql_subscription(...args) { return ditto.ditto_experimental_add_dql_subscription(...args) }
|
|
329
|
-
function ditto_experimental_exec_statement_str(...args) { return ditto.ditto_experimental_exec_statement_str(...args) }
|
|
330
341
|
function ditto_experimental_register_dql_live_query_str_detached(...args) { return ditto.ditto_experimental_register_dql_live_query_str_detached(...args) }
|
|
331
342
|
function ditto_experimental_remove_dql_subscription(...args) { return ditto.ditto_experimental_remove_dql_subscription(...args) }
|
|
332
343
|
function ditto_experimental_webhook_register_dql_live_query_str(...args) { return ditto.ditto_experimental_webhook_register_dql_live_query_str(...args) }
|
|
@@ -369,6 +380,7 @@ function ditto_register_transport_condition_changed_callback(...args) { return d
|
|
|
369
380
|
function ditto_remove_multicast_transport(...args) { return ditto.ditto_remove_multicast_transport(...args) }
|
|
370
381
|
function ditto_remove_subscription(...args) { return ditto.ditto_remove_subscription(...args) }
|
|
371
382
|
function ditto_resolve_attachment(...args) { return ditto.ditto_resolve_attachment(...args) }
|
|
383
|
+
function ditto_result_cbor(...args) { return ditto.ditto_result_cbor(...args) }
|
|
372
384
|
function ditto_run_garbage_collection(...args) { return ditto.ditto_run_garbage_collection(...args) }
|
|
373
385
|
function ditto_set_connect_retry_interval(...args) { return ditto.ditto_set_connect_retry_interval(...args) }
|
|
374
386
|
function ditto_set_device_name(...args) { return ditto.ditto_set_device_name(...args) }
|
|
@@ -385,6 +397,9 @@ function ditto_validate_document_id(...args) { return ditto.ditto_validate_docum
|
|
|
385
397
|
function ditto_write_transaction(...args) { return ditto.ditto_write_transaction(...args) }
|
|
386
398
|
function ditto_write_transaction_commit(...args) { return ditto.ditto_write_transaction_commit(...args) }
|
|
387
399
|
function ditto_write_transaction_rollback(...args) { return ditto.ditto_write_transaction_rollback(...args) }
|
|
400
|
+
function dittoffi_error_description(...args) { return ditto.dittoffi_error_description(...args) }
|
|
401
|
+
function dittoffi_error_free(...args) { return ditto.dittoffi_error_free(...args) }
|
|
402
|
+
function dittoffi_try_experimental_exec_statement_str(...args) { return ditto.dittoffi_try_experimental_exec_statement_str(...args) }
|
|
388
403
|
function getDeadlockTimeout$1(...args) { return ditto.getDeadlockTimeout(...args) }
|
|
389
404
|
function jsDocsToCDocs(...args) { return ditto.jsDocsToCDocs(...args) }
|
|
390
405
|
function mdns_client_free_handle(...args) { return ditto.mdns_client_free_handle(...args) }
|
|
@@ -636,13 +651,27 @@ async function collectionEvictQueryStr(ditto, collectionName, writeTransaction,
|
|
|
636
651
|
const queryX = bytesFromString(query);
|
|
637
652
|
return await ditto_collection_evict_query_str(ditto, collectionNameX, writeTransaction, queryX, queryArgsCBOR, orderBy, limit, offset);
|
|
638
653
|
}
|
|
639
|
-
/**
|
|
654
|
+
/**
|
|
655
|
+
* This FFI can error:
|
|
656
|
+
* - DQL parser error
|
|
657
|
+
* - Incorrect arguments to query parameters
|
|
658
|
+
* - Collection is not found.
|
|
659
|
+
*
|
|
660
|
+
* @internal
|
|
661
|
+
*/
|
|
640
662
|
async function experimentalExecQueryStr(ditto, writeTransaction, query, queryArgsCBOR) {
|
|
641
663
|
ensureInitialized();
|
|
642
664
|
const queryBytesPointer = bytesFromString(query);
|
|
643
665
|
// This doesn't need to convert error return codes into thrown js errors
|
|
644
666
|
// because the ffi implementation already does that.
|
|
645
|
-
|
|
667
|
+
const result = await dittoffi_try_experimental_exec_statement_str(ditto, writeTransaction, queryBytesPointer, queryArgsCBOR);
|
|
668
|
+
if (result.error !== null) {
|
|
669
|
+
// TODO: idiomatic js error class shim around `Pointer<FFIError>`.
|
|
670
|
+
const errorMsg = errorMessage(result.error);
|
|
671
|
+
dittoffi_error_free(result.error);
|
|
672
|
+
throw new Error(errorMsg);
|
|
673
|
+
}
|
|
674
|
+
return result.success;
|
|
646
675
|
}
|
|
647
676
|
/** @internal */
|
|
648
677
|
function addSubscription(ditto, collectionName, query, queryArgsCBOR, orderBy, limit, offset) {
|
|
@@ -674,6 +703,49 @@ function experimentalRemoveDqlSubscription(ditto, query, queryArgsCBOR) {
|
|
|
674
703
|
if (statusCode !== 0)
|
|
675
704
|
throw new Error(errorMessage() || `ditto_experimental_remove_dql_subscription() failed with error code: ${statusCode}`);
|
|
676
705
|
}
|
|
706
|
+
// ----------------------------------------------------------- DqlResponse ------
|
|
707
|
+
/**
|
|
708
|
+
* Doesn't error
|
|
709
|
+
*
|
|
710
|
+
* @internal
|
|
711
|
+
*/
|
|
712
|
+
function experimentalDqlResponseFree(self) {
|
|
713
|
+
ensureInitialized();
|
|
714
|
+
ditto_dql_response_free(self);
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* Doesn't error
|
|
718
|
+
*
|
|
719
|
+
* @internal
|
|
720
|
+
*/
|
|
721
|
+
function experimentalDqlResultFree(self) {
|
|
722
|
+
ensureInitialized();
|
|
723
|
+
ditto_dql_result_free(self);
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Can error only on internal bug.
|
|
727
|
+
*
|
|
728
|
+
* @internal */
|
|
729
|
+
function experimentalDqlResponseResults(self) {
|
|
730
|
+
ensureInitialized();
|
|
731
|
+
return ditto_dql_response_results(self);
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* The result CBOR contains a map/object with fields and values.
|
|
735
|
+
* No CRDTs are present there as they are not needed. Currently
|
|
736
|
+
* only values from registers are returned and non-register fields are
|
|
737
|
+
* ignored. Reading values from other CRDTs will be supported with
|
|
738
|
+
* definition support.
|
|
739
|
+
*
|
|
740
|
+
* Doesn't error
|
|
741
|
+
*
|
|
742
|
+
* @internal
|
|
743
|
+
*/
|
|
744
|
+
function experimentalDqlResultCBOR(self) {
|
|
745
|
+
ensureInitialized();
|
|
746
|
+
const cborBytes = ditto_result_cbor(self);
|
|
747
|
+
return boxCBytesIntoBuffer(cborBytes);
|
|
748
|
+
}
|
|
677
749
|
// ------------------------------------------------------------ LiveQuery ------
|
|
678
750
|
/** @internal */
|
|
679
751
|
function liveQueryRegister(ditto, collectionName, query, queryArgsCBOR, orderBy, limit, offset, eventHandler,
|
|
@@ -1342,9 +1414,12 @@ function bytesFromString(jsString) {
|
|
|
1342
1414
|
return textEncoder.encode(`${jsString}\0`);
|
|
1343
1415
|
}
|
|
1344
1416
|
/** @internal */
|
|
1345
|
-
function errorMessage() {
|
|
1417
|
+
function errorMessage(ffiError) {
|
|
1346
1418
|
ensureInitialized();
|
|
1347
|
-
|
|
1419
|
+
// eslint-disable-next-line
|
|
1420
|
+
const errorMessageCString = (typeof ffiError === 'undefined'
|
|
1421
|
+
? ditto_error_message()
|
|
1422
|
+
: dittoffi_error_description(ffiError));
|
|
1348
1423
|
return boxCStringIntoString(errorMessageCString);
|
|
1349
1424
|
}
|
|
1350
1425
|
/** @internal */
|
|
@@ -1521,7 +1596,7 @@ function awdlDestroy(awdl) {
|
|
|
1521
1596
|
|
|
1522
1597
|
// NOTE: this is patched up with the actual build version by Jake task
|
|
1523
1598
|
// build:package and has to be a valid semantic version as defined here: https://semver.org.
|
|
1524
|
-
const fullBuildVersionString = '4.4.
|
|
1599
|
+
const fullBuildVersionString = '4.4.2-alpha1';
|
|
1525
1600
|
|
|
1526
1601
|
//
|
|
1527
1602
|
// Copyright © 2021 DittoLive Incorporated. All rights reserved.
|
|
@@ -1563,6 +1638,13 @@ async function init(options = {}) {
|
|
|
1563
1638
|
* log messages with the Ditto logging infrastructure.
|
|
1564
1639
|
*/
|
|
1565
1640
|
class Logger {
|
|
1641
|
+
/**
|
|
1642
|
+
* Registers a file path where logs will be written to, whenever Ditto wants
|
|
1643
|
+
* to issue a log (on _top_ of emitting the log to the console).
|
|
1644
|
+
*/
|
|
1645
|
+
static get logFile() {
|
|
1646
|
+
return this._logFile;
|
|
1647
|
+
}
|
|
1566
1648
|
/**
|
|
1567
1649
|
* On Node, registers a file path where logs will be written to, whenever
|
|
1568
1650
|
* Ditto wants to issue a log (on _top_ of emitting the log to the console).
|
|
@@ -1575,11 +1657,11 @@ class Logger {
|
|
|
1575
1657
|
static setLogFile(path) {
|
|
1576
1658
|
if (path) {
|
|
1577
1659
|
loggerSetLogFile(path);
|
|
1578
|
-
this
|
|
1660
|
+
this._logFile = path;
|
|
1579
1661
|
}
|
|
1580
1662
|
else {
|
|
1581
|
-
loggerSetLogFile(
|
|
1582
|
-
delete this
|
|
1663
|
+
loggerSetLogFile(undefined);
|
|
1664
|
+
delete this._logFile;
|
|
1583
1665
|
}
|
|
1584
1666
|
}
|
|
1585
1667
|
/**
|
|
@@ -1587,7 +1669,8 @@ class Logger {
|
|
|
1587
1669
|
* {@link setLogFile | setLogFile()} with it.
|
|
1588
1670
|
*/
|
|
1589
1671
|
static setLogFileURL(url) {
|
|
1590
|
-
|
|
1672
|
+
var _a;
|
|
1673
|
+
this.setLogFile((_a = url === null || url === void 0 ? void 0 : url.pathname) !== null && _a !== void 0 ? _a : null);
|
|
1591
1674
|
}
|
|
1592
1675
|
/** Whether the logger is currently enabled. */
|
|
1593
1676
|
static get enabled() {
|
|
@@ -1629,6 +1712,14 @@ class Logger {
|
|
|
1629
1712
|
static set minimumLogLevel(minimumLogLevel) {
|
|
1630
1713
|
loggerMinimumLogLevel(minimumLogLevel);
|
|
1631
1714
|
}
|
|
1715
|
+
/**
|
|
1716
|
+
* Returns the current custom log callback, `undefined` by default. See
|
|
1717
|
+
* {@link setCustomLogCallback | setCustomLogCallback()} for a detailed
|
|
1718
|
+
* description.
|
|
1719
|
+
*/
|
|
1720
|
+
static get customLogCallback() {
|
|
1721
|
+
return this._customLogCallback;
|
|
1722
|
+
}
|
|
1632
1723
|
/**
|
|
1633
1724
|
* Registers a custom callback that will be called to report each log entry.
|
|
1634
1725
|
*
|
|
@@ -1639,11 +1730,11 @@ class Logger {
|
|
|
1639
1730
|
static async setCustomLogCallback(callback) {
|
|
1640
1731
|
if (callback) {
|
|
1641
1732
|
await loggerSetCustomLogCb(callback);
|
|
1642
|
-
this
|
|
1733
|
+
this._customLogCallback = callback;
|
|
1643
1734
|
}
|
|
1644
1735
|
else {
|
|
1645
1736
|
await loggerSetCustomLogCb(null);
|
|
1646
|
-
delete this
|
|
1737
|
+
delete this._customLogCallback;
|
|
1647
1738
|
}
|
|
1648
1739
|
}
|
|
1649
1740
|
/**
|
|
@@ -1693,7 +1784,6 @@ class Logger {
|
|
|
1693
1784
|
static verbose(message) {
|
|
1694
1785
|
this.log('Verbose', message);
|
|
1695
1786
|
}
|
|
1696
|
-
// ------------------------------------------------------------ Private ------
|
|
1697
1787
|
constructor() {
|
|
1698
1788
|
throw new Error("Logger can't be instantiated, use its static properties & methods directly instead.");
|
|
1699
1789
|
}
|
|
@@ -2839,7 +2929,7 @@ function validateDocumentIDCBOR(idCBOR) {
|
|
|
2839
2929
|
}
|
|
2840
2930
|
|
|
2841
2931
|
//
|
|
2842
|
-
// Copyright ©
|
|
2932
|
+
// Copyright © 2023 DittoLive Incorporated. All rights reserved.
|
|
2843
2933
|
//
|
|
2844
2934
|
// REFACTOR: tweak the API to use Rust concepts of ownership. For example,
|
|
2845
2935
|
// register() could be named something like yieldOwnership() while unregister()
|
|
@@ -3284,6 +3374,10 @@ Bridge.document = new Bridge(documentFree);
|
|
|
3284
3374
|
/** @internal */
|
|
3285
3375
|
Bridge.mutableDocument = new Bridge(documentFree);
|
|
3286
3376
|
/** @internal */
|
|
3377
|
+
Bridge.dqlResponse = new Bridge(experimentalDqlResponseFree);
|
|
3378
|
+
/** @internal */
|
|
3379
|
+
Bridge.dqlResult = new Bridge(experimentalDqlResultFree);
|
|
3380
|
+
/** @internal */
|
|
3287
3381
|
Bridge.staticTCPClient = new Bridge(staticTCPClientFreeHandle);
|
|
3288
3382
|
/** @internal */
|
|
3289
3383
|
Bridge.websocketClient = new Bridge(websocketClientFreeHandle);
|
|
@@ -4584,6 +4678,12 @@ class ObserverManager {
|
|
|
4584
4678
|
* `OnlineWithAuthentication` or an `Online` identity.
|
|
4585
4679
|
*/
|
|
4586
4680
|
class Authenticator {
|
|
4681
|
+
/**
|
|
4682
|
+
Returns the current authentication status.
|
|
4683
|
+
*/
|
|
4684
|
+
get status() {
|
|
4685
|
+
return this._status;
|
|
4686
|
+
}
|
|
4587
4687
|
/**
|
|
4588
4688
|
* Log in to Ditto with a third-party token. Throws if authentication is not
|
|
4589
4689
|
* available, which can be checked with {@link loginSupported}.
|
|
@@ -4632,7 +4732,7 @@ class Authenticator {
|
|
|
4632
4732
|
/** @internal */
|
|
4633
4733
|
constructor(keepAlive) {
|
|
4634
4734
|
this.keepAlive = keepAlive;
|
|
4635
|
-
this.
|
|
4735
|
+
this._status = { isAuthenticated: false, userID: null };
|
|
4636
4736
|
this.loginSupported = false;
|
|
4637
4737
|
this.observerManager = new ObserverManager('AuthenticationStatusObservation', { keepAlive });
|
|
4638
4738
|
}
|
|
@@ -4693,13 +4793,13 @@ class OnlineAuthenticator extends Authenticator {
|
|
|
4693
4793
|
return ditto.deferCloseAsync(async () => {
|
|
4694
4794
|
await dittoAuthClientLogout(dittoPointer);
|
|
4695
4795
|
ditto.stopSync();
|
|
4696
|
-
cleanupFn === null || cleanupFn === void 0 ? void 0 : cleanupFn(
|
|
4796
|
+
cleanupFn === null || cleanupFn === void 0 ? void 0 : cleanupFn(ditto);
|
|
4697
4797
|
});
|
|
4698
4798
|
}
|
|
4699
4799
|
constructor(keepAlive, ditto, authenticationHandler) {
|
|
4700
4800
|
super(keepAlive);
|
|
4701
|
-
this
|
|
4702
|
-
this
|
|
4801
|
+
this.loginSupported = true;
|
|
4802
|
+
this._status = { isAuthenticated: false, userID: null };
|
|
4703
4803
|
this.ditto = new WeakRef(ditto);
|
|
4704
4804
|
this.authenticationHandler = authenticationHandler;
|
|
4705
4805
|
this.updateAndNotify(false);
|
|
@@ -4734,7 +4834,7 @@ class OnlineAuthenticator extends Authenticator {
|
|
|
4734
4834
|
const isAuthenticated = dittoAuthClientIsWebValid(dittoPointer);
|
|
4735
4835
|
const userID = dittoAuthClientUserID(dittoPointer);
|
|
4736
4836
|
const status = { isAuthenticated, userID };
|
|
4737
|
-
this
|
|
4837
|
+
this._status = status;
|
|
4738
4838
|
if (shouldNotify) {
|
|
4739
4839
|
const sameStatus = !!wasAuthenticated === !!isAuthenticated && previousUserID === userID;
|
|
4740
4840
|
if (!sameStatus) {
|
|
@@ -4927,6 +5027,7 @@ class TransportConfig {
|
|
|
4927
5027
|
* Create a new transport config initialized with the default settings.
|
|
4928
5028
|
*/
|
|
4929
5029
|
constructor() {
|
|
5030
|
+
this._isFrozen = false;
|
|
4930
5031
|
this.peerToPeer = {
|
|
4931
5032
|
bluetoothLE: { isEnabled: false },
|
|
4932
5033
|
awdl: { isEnabled: false },
|
|
@@ -4963,13 +5064,20 @@ class TransportConfig {
|
|
|
4963
5064
|
this.peerToPeer.lan.isEnabled = enabled;
|
|
4964
5065
|
this.peerToPeer.awdl.isEnabled = enabled;
|
|
4965
5066
|
}
|
|
5067
|
+
/**
|
|
5068
|
+
* Returns `true` if the transport configuration is frozen, otherwise
|
|
5069
|
+
* returns `false`.
|
|
5070
|
+
*/
|
|
5071
|
+
get isFrozen() {
|
|
5072
|
+
return this._isFrozen;
|
|
5073
|
+
}
|
|
4966
5074
|
/**
|
|
4967
5075
|
* (Deep) freezes the receiver such that it can't be modified anymore.
|
|
4968
5076
|
*/
|
|
4969
5077
|
freeze() {
|
|
4970
5078
|
if (this.isFrozen)
|
|
4971
5079
|
return this;
|
|
4972
|
-
this
|
|
5080
|
+
this._isFrozen = true;
|
|
4973
5081
|
Object.freeze(this.peerToPeer.bluetoothLE);
|
|
4974
5082
|
Object.freeze(this.peerToPeer.awdl);
|
|
4975
5083
|
Object.freeze(this.peerToPeer.lan);
|
|
@@ -4996,8 +5104,8 @@ class TransportConfig {
|
|
|
4996
5104
|
copy.connect.tcpServers = this.connect.tcpServers.slice();
|
|
4997
5105
|
copy.connect.websocketURLs = this.connect.websocketURLs.slice();
|
|
4998
5106
|
copy.connect.retryInterval = this.connect.retryInterval;
|
|
4999
|
-
copy.listen
|
|
5000
|
-
copy.listen
|
|
5107
|
+
copy.listen.tcp = { ...this.listen.tcp };
|
|
5108
|
+
copy.listen.http = { ...this.listen.http };
|
|
5001
5109
|
copy.global.syncGroup = this.global.syncGroup;
|
|
5002
5110
|
copy.global.routingHint = this.global.routingHint;
|
|
5003
5111
|
return copy;
|
|
@@ -5008,6 +5116,7 @@ class TransportConfig {
|
|
|
5008
5116
|
*/
|
|
5009
5117
|
static areListenTCPsEqual(left, right) {
|
|
5010
5118
|
/* eslint-disable */
|
|
5119
|
+
// prettier-ignore
|
|
5011
5120
|
return (left.isEnabled === right.isEnabled &&
|
|
5012
5121
|
left.interfaceIP === right.interfaceIP &&
|
|
5013
5122
|
left.port === right.port);
|
|
@@ -5019,6 +5128,7 @@ class TransportConfig {
|
|
|
5019
5128
|
*/
|
|
5020
5129
|
static areListenHTTPsEqual(left, right) {
|
|
5021
5130
|
/* eslint-disable */
|
|
5131
|
+
// prettier-ignore
|
|
5022
5132
|
return (left.isEnabled === right.isEnabled &&
|
|
5023
5133
|
left.interfaceIP === right.interfaceIP &&
|
|
5024
5134
|
left.port === right.port &&
|
|
@@ -5042,6 +5152,13 @@ class TransportConfig {
|
|
|
5042
5152
|
* try to be kept up-to-date with the latest changes from remote peers.
|
|
5043
5153
|
*/
|
|
5044
5154
|
class Subscription {
|
|
5155
|
+
/**
|
|
5156
|
+
* Returns `true` if subscription has been explicitly cancelled, `false`
|
|
5157
|
+
* otherwise.
|
|
5158
|
+
*/
|
|
5159
|
+
get isCancelled() {
|
|
5160
|
+
return this._isCancelled;
|
|
5161
|
+
}
|
|
5045
5162
|
/**
|
|
5046
5163
|
* The name of the collection that the subscription is based on.
|
|
5047
5164
|
*/
|
|
@@ -5053,18 +5170,14 @@ class Subscription {
|
|
|
5053
5170
|
*/
|
|
5054
5171
|
cancel() {
|
|
5055
5172
|
if (!this.isCancelled) {
|
|
5056
|
-
this
|
|
5173
|
+
this._isCancelled = true;
|
|
5057
5174
|
this.manager.remove(this);
|
|
5058
5175
|
}
|
|
5059
5176
|
}
|
|
5060
5177
|
// ----------------------------------------------------------- Internal ------
|
|
5061
5178
|
/** @internal */
|
|
5062
5179
|
constructor(collection, query, queryArgsCBOR, orderBys, limit, offset) {
|
|
5063
|
-
|
|
5064
|
-
* Returns `true` if subscription has been explicitly cancelled, `false`
|
|
5065
|
-
* otherwise.
|
|
5066
|
-
*/
|
|
5067
|
-
this.isCancelled = false;
|
|
5180
|
+
this._isCancelled = false;
|
|
5068
5181
|
// Query should be validated at this point.
|
|
5069
5182
|
this.query = query;
|
|
5070
5183
|
this.queryArgsCBOR = queryArgsCBOR;
|
|
@@ -5230,6 +5343,9 @@ class LiveQuery {
|
|
|
5230
5343
|
this.liveQueryManager.stopLiveQuery(this);
|
|
5231
5344
|
}
|
|
5232
5345
|
}
|
|
5346
|
+
get liveQueryID() {
|
|
5347
|
+
return this._liveQueryID;
|
|
5348
|
+
}
|
|
5233
5349
|
/** @internal */
|
|
5234
5350
|
constructor(query, queryArgs, queryArgsCBOR, orderBys, limit, offset, collection, handler) {
|
|
5235
5351
|
// Query should be validated at this point.
|
|
@@ -5277,11 +5393,11 @@ class LiveQuery {
|
|
|
5277
5393
|
}
|
|
5278
5394
|
handler(documents, event, signalNext);
|
|
5279
5395
|
});
|
|
5280
|
-
if (!liveQueryID) {
|
|
5281
|
-
throw new Error("Internal inconsistency, couldn't create a valid live query ID.");
|
|
5282
|
-
}
|
|
5283
|
-
this['liveQueryID'] = liveQueryID;
|
|
5284
5396
|
});
|
|
5397
|
+
if (!liveQueryID) {
|
|
5398
|
+
throw new Error("Internal inconsistency, couldn't create a valid live query ID.");
|
|
5399
|
+
}
|
|
5400
|
+
this._liveQueryID = liveQueryID;
|
|
5285
5401
|
}
|
|
5286
5402
|
/** @internal */
|
|
5287
5403
|
async signalNext() {
|
|
@@ -6360,26 +6476,29 @@ class ExperimentalReplicationSubscriptionManager {
|
|
|
6360
6476
|
* @internal
|
|
6361
6477
|
*/
|
|
6362
6478
|
class ExperimentalReplicationSubscription {
|
|
6479
|
+
/**
|
|
6480
|
+
* `true` when {@link cancel | cancel()} has been called or the Ditto instance
|
|
6481
|
+
* managing this replication subscription has been closed.
|
|
6482
|
+
*/
|
|
6483
|
+
// Recording this information on the replication subscription instance itself
|
|
6484
|
+
// allows working with it even after Ditto has been closed and the replication
|
|
6485
|
+
// subscription manager can not be accessed anymore.
|
|
6486
|
+
get isCancelled() {
|
|
6487
|
+
return this._isCancelled;
|
|
6488
|
+
}
|
|
6363
6489
|
/**
|
|
6364
6490
|
* Cancels a replication subscription and releases all associated resources.
|
|
6365
6491
|
*/
|
|
6366
6492
|
cancel() {
|
|
6367
6493
|
if (!this.isCancelled) {
|
|
6368
|
-
this
|
|
6494
|
+
this._isCancelled = true;
|
|
6369
6495
|
this.manager.removeSubscription(this);
|
|
6370
6496
|
}
|
|
6371
6497
|
}
|
|
6372
6498
|
// --------------------------- Internal --------------------------------------
|
|
6373
6499
|
/** @internal */
|
|
6374
6500
|
constructor(manager, query, queryArgsCBOR) {
|
|
6375
|
-
|
|
6376
|
-
* `true` when {@link cancel | cancel()} has been called or the Ditto instance
|
|
6377
|
-
* managing this replication subscription has been closed.
|
|
6378
|
-
*/
|
|
6379
|
-
// Recording this information on the replication subscription instance itself
|
|
6380
|
-
// allows working with it even after Ditto has been closed and the replication
|
|
6381
|
-
// subscription manager can not be accessed anymore.
|
|
6382
|
-
this.isCancelled = false;
|
|
6501
|
+
this._isCancelled = false;
|
|
6383
6502
|
this.query = query;
|
|
6384
6503
|
this.queryArgsCBOR = queryArgsCBOR;
|
|
6385
6504
|
this.contextInfo = {
|
|
@@ -6480,14 +6599,23 @@ class ExperimentalStore {
|
|
|
6480
6599
|
* The returned {@link ExperimentalReplicationSubscription} object must be kept in scope
|
|
6481
6600
|
* for as long as you want to keep receiving updates.
|
|
6482
6601
|
*
|
|
6602
|
+
* Use placeholders to incorporate values from the optional `queryArguments`
|
|
6603
|
+
* parameter into the query. The keys of the `queryArguments` object must
|
|
6604
|
+
* match the placeholders used within the query. You can not use placeholders
|
|
6605
|
+
* in the `FROM` clause.
|
|
6606
|
+
*
|
|
6483
6607
|
* @internal
|
|
6484
6608
|
* @param query a Ditto Query Language query string of the form SELECT * FROM
|
|
6485
6609
|
* collection WHERE expression
|
|
6610
|
+
* @param queryArguments an object with values to be incorporated into a
|
|
6611
|
+
* query. The keys of the object must match the placeholders used within the
|
|
6612
|
+
* query.
|
|
6486
6613
|
* @returns {@link ExperimentalReplicationSubscription} object
|
|
6487
6614
|
*/
|
|
6488
|
-
addReplicationSubscription(query) {
|
|
6615
|
+
addReplicationSubscription(query, queryArguments) {
|
|
6489
6616
|
Logger.debug(`ExperimentalStore.subscribe(query = ${query})`);
|
|
6490
|
-
|
|
6617
|
+
const queryArgumentsCBOR = queryArguments ? CBOR.encode(queryArguments) : null;
|
|
6618
|
+
return new ExperimentalReplicationSubscription(this.replicationSubscriptionManager, query, queryArgumentsCBOR);
|
|
6491
6619
|
}
|
|
6492
6620
|
/** @internal */
|
|
6493
6621
|
close() {
|
|
@@ -6497,18 +6625,25 @@ class ExperimentalStore {
|
|
|
6497
6625
|
/**
|
|
6498
6626
|
* Executes the given query in the local store and returns the result.
|
|
6499
6627
|
*
|
|
6628
|
+
* Use placeholders to incorporate values from the optional `queryArguments`
|
|
6629
|
+
* parameter into the query. The keys of the `queryArguments` object must
|
|
6630
|
+
* match the placeholders used within the query. You can not use placeholders
|
|
6631
|
+
* in the `FROM` clause.
|
|
6632
|
+
*
|
|
6500
6633
|
* Limitations:
|
|
6501
6634
|
*
|
|
6502
6635
|
* - Supports `SELECT * FROM <collection name>` with optional `WHERE
|
|
6503
6636
|
* <expression>`
|
|
6504
|
-
* - No query parameters as function arguments yet
|
|
6505
6637
|
* - No transactions
|
|
6506
6638
|
*
|
|
6507
6639
|
* @internal
|
|
6508
6640
|
* @param query a Ditto Query Language query string
|
|
6641
|
+
* @param queryArguments an object with values to be incorporated into a
|
|
6642
|
+
* query. The keys of the object must match the placeholders used within the
|
|
6643
|
+
* query.
|
|
6509
6644
|
* @returns a promise for an array of Ditto documents matching the query
|
|
6510
6645
|
*/
|
|
6511
|
-
async execute(query) {
|
|
6646
|
+
async execute(query, queryArguments) {
|
|
6512
6647
|
Logger.debug(`ExperimentalStore.execute(query = ${query})`);
|
|
6513
6648
|
const ditto = this.ditto;
|
|
6514
6649
|
const dittoHandle = Bridge.ditto.handleFor(ditto);
|
|
@@ -6516,12 +6651,11 @@ class ExperimentalStore {
|
|
|
6516
6651
|
// A one-off query execution uses a transaction internally but a
|
|
6517
6652
|
// transaction API is not implemented yet.
|
|
6518
6653
|
const writeTransaction = null;
|
|
6519
|
-
|
|
6520
|
-
const
|
|
6521
|
-
|
|
6522
|
-
return await experimentalExecQueryStr(dittoHandle.deref(), writeTransaction, query, queryParameters);
|
|
6654
|
+
const queryArgumentsCBOR = queryArguments ? CBOR.encode(queryArguments) : null;
|
|
6655
|
+
const responsePointer = await performAsyncToWorkaroundNonAsyncFFIAPI(async () => {
|
|
6656
|
+
return await experimentalExecQueryStr(dittoHandle.deref(), writeTransaction, query, queryArgumentsCBOR);
|
|
6523
6657
|
});
|
|
6524
|
-
return
|
|
6658
|
+
return Bridge.dqlResponse.bridge(responsePointer);
|
|
6525
6659
|
});
|
|
6526
6660
|
}
|
|
6527
6661
|
}
|
|
@@ -7303,6 +7437,9 @@ class TransportConditionsManager extends ObserverManager {
|
|
|
7303
7437
|
//
|
|
7304
7438
|
/** @internal */
|
|
7305
7439
|
class Sync {
|
|
7440
|
+
get parameters() {
|
|
7441
|
+
return this._parameters;
|
|
7442
|
+
}
|
|
7306
7443
|
constructor(ditto) {
|
|
7307
7444
|
this.bluetoothLETransportPointer = null;
|
|
7308
7445
|
this.awdlTransportPointer = null;
|
|
@@ -7313,11 +7450,11 @@ class Sync {
|
|
|
7313
7450
|
const transportConfig = new TransportConfig();
|
|
7314
7451
|
const parameters = { identity, transportConfig, ditto, isWebValid: false, isX509Valid: false, isSyncActive: false };
|
|
7315
7452
|
this.ditto = ditto;
|
|
7316
|
-
this.
|
|
7453
|
+
this._parameters = parameters;
|
|
7317
7454
|
this.state = stateFrom(parameters);
|
|
7318
7455
|
}
|
|
7319
7456
|
update(parameters) {
|
|
7320
|
-
this
|
|
7457
|
+
this._parameters = { ...parameters };
|
|
7321
7458
|
// NOTE: updating is a two-step process. Given all parameters, we
|
|
7322
7459
|
// first compute the final "state" we want the transports stuff to
|
|
7323
7460
|
// be in via the `stateFrom()` function. We then take that "desired" state
|
|
@@ -7897,6 +8034,32 @@ class Ditto {
|
|
|
7897
8034
|
Logger.warning("⚠️ Deprecation Warning: The 'Ditto.path' property is deprecated. Please update your code to use the new 'Ditto.persistenceDirectory' property instead.");
|
|
7898
8035
|
return this.persistenceDirectory;
|
|
7899
8036
|
}
|
|
8037
|
+
/**
|
|
8038
|
+
* Returns `true` if an offline license token has been set, otherwise returns `false`.
|
|
8039
|
+
*
|
|
8040
|
+
* @see {@link setOfflineOnlyLicenseToken | setOfflineOnlyLicenseToken()}
|
|
8041
|
+
*/
|
|
8042
|
+
get isActivated() {
|
|
8043
|
+
var _a;
|
|
8044
|
+
return (_a = this._isActivated) !== null && _a !== void 0 ? _a : false;
|
|
8045
|
+
}
|
|
8046
|
+
/**
|
|
8047
|
+
* `true` once {@link close | Ditto.close()} has been called, otherwise
|
|
8048
|
+
* `false`.
|
|
8049
|
+
*/
|
|
8050
|
+
get isClosed() {
|
|
8051
|
+
var _a;
|
|
8052
|
+
return (_a = this._isClosed) !== null && _a !== void 0 ? _a : false;
|
|
8053
|
+
}
|
|
8054
|
+
/**
|
|
8055
|
+
* Returns `true` if sync is active, otherwise returns `false`. Use
|
|
8056
|
+
* {@link startSync | startSync()} to activate and
|
|
8057
|
+
* {@link stopSync | stopSync()} to deactivate sync.
|
|
8058
|
+
*/
|
|
8059
|
+
get isSyncActive() {
|
|
8060
|
+
var _a;
|
|
8061
|
+
return (_a = this._isSyncActive) !== null && _a !== void 0 ? _a : false;
|
|
8062
|
+
}
|
|
7900
8063
|
/**
|
|
7901
8064
|
* Initializes a new `Ditto` instance.
|
|
7902
8065
|
*
|
|
@@ -7915,14 +8078,11 @@ class Ditto {
|
|
|
7915
8078
|
* @see {@link Ditto.persistenceDirectory}
|
|
7916
8079
|
*/
|
|
7917
8080
|
constructor(identity, persistenceDirectory) {
|
|
7918
|
-
/**
|
|
7919
|
-
* `true` once {@link close | Ditto.close()} has been called, otherwise
|
|
7920
|
-
* `false`.
|
|
7921
|
-
*/
|
|
7922
|
-
this.isClosed = false;
|
|
7923
8081
|
this.deferCloseAllowed = true;
|
|
7924
8082
|
this.isWebValid = false;
|
|
7925
8083
|
this.isX509Valid = false;
|
|
8084
|
+
this._isSyncActive = false;
|
|
8085
|
+
this._isClosed = false;
|
|
7926
8086
|
/** Set of pending operations that need to complete before the Ditto instance can be closed in a safe manner. */
|
|
7927
8087
|
this.pendingOperations = new Set();
|
|
7928
8088
|
if (!Ditto.isEnvironmentSupported()) {
|
|
@@ -8036,14 +8196,14 @@ class Ditto {
|
|
|
8036
8196
|
//
|
|
8037
8197
|
this.appID = appID;
|
|
8038
8198
|
this.siteID = siteID;
|
|
8039
|
-
this.
|
|
8199
|
+
this._transportConfig = transportConfig.copy().freeze();
|
|
8040
8200
|
this.isX509Valid = isX509Valid;
|
|
8041
8201
|
this.isWebValid = isWebValid;
|
|
8042
8202
|
this.sync = new Sync(this);
|
|
8043
8203
|
this.sync.update({ isSyncActive: false, isX509Valid, isWebValid, identity: validIdentity, ditto: this, transportConfig });
|
|
8044
8204
|
// We don't need a license when running in the browser, so we
|
|
8045
8205
|
// mark the instance as activated from the get-go in that case.
|
|
8046
|
-
this.
|
|
8206
|
+
this._isActivated = !IdentityTypesRequiringOfflineLicenseToken.includes(validIdentity.type);
|
|
8047
8207
|
this.store = new Store(this);
|
|
8048
8208
|
this.presence = new Presence(this);
|
|
8049
8209
|
this.presenceManager = new PresenceManager(this);
|
|
@@ -8207,11 +8367,11 @@ class Ditto {
|
|
|
8207
8367
|
if (IdentityTypesRequiringOfflineLicenseToken.includes(this.identity.type)) {
|
|
8208
8368
|
const { result, errorMessage } = verifyLicense(licenseToken);
|
|
8209
8369
|
if (result !== 'LicenseOk') {
|
|
8210
|
-
this
|
|
8370
|
+
this._isActivated = false;
|
|
8211
8371
|
throw new Error(errorMessage);
|
|
8212
8372
|
}
|
|
8213
8373
|
else {
|
|
8214
|
-
this
|
|
8374
|
+
this._isActivated = true;
|
|
8215
8375
|
}
|
|
8216
8376
|
}
|
|
8217
8377
|
else {
|
|
@@ -8219,6 +8379,20 @@ class Ditto {
|
|
|
8219
8379
|
}
|
|
8220
8380
|
}
|
|
8221
8381
|
}
|
|
8382
|
+
/**
|
|
8383
|
+
* Returns the current transport configuration, frozen. If you want to modify
|
|
8384
|
+
* the transport config, make a {@link TransportConfig.copy | copy} first. Or
|
|
8385
|
+
* use the {@link updateTransportConfig | updateTransportConfig()}
|
|
8386
|
+
* convenience method. By default peer-to-peer transports (Bluetooth, WiFi,
|
|
8387
|
+
* and AWDL) are enabled if available in the current environment
|
|
8388
|
+
* (Web, Node, OS, etc.).
|
|
8389
|
+
*
|
|
8390
|
+
* @see {@link setTransportConfig | setTransportConfig()}
|
|
8391
|
+
* @see {@link updateTransportConfig | updateTransportConfig()}
|
|
8392
|
+
*/
|
|
8393
|
+
get transportConfig() {
|
|
8394
|
+
return this._transportConfig;
|
|
8395
|
+
}
|
|
8222
8396
|
/**
|
|
8223
8397
|
* Assigns a new transports configuration. By default peer-to-peer transports
|
|
8224
8398
|
* (Bluetooth, WiFi, and AWDL) are enabled. You may use this method to alter
|
|
@@ -8229,7 +8403,7 @@ class Ditto {
|
|
|
8229
8403
|
* @see {@link updateTransportConfig | updateTransportConfig()}
|
|
8230
8404
|
*/
|
|
8231
8405
|
setTransportConfig(transportConfig) {
|
|
8232
|
-
this
|
|
8406
|
+
this._transportConfig = transportConfig.copy().freeze();
|
|
8233
8407
|
const transportConfigNew = this.transportConfig;
|
|
8234
8408
|
const identity = this.identity;
|
|
8235
8409
|
const isWebValid = this.isWebValid;
|
|
@@ -8366,7 +8540,7 @@ class Ditto {
|
|
|
8366
8540
|
if (this.isClosed) {
|
|
8367
8541
|
return;
|
|
8368
8542
|
}
|
|
8369
|
-
this
|
|
8543
|
+
this._isClosed = true;
|
|
8370
8544
|
this.stopSync();
|
|
8371
8545
|
this.store.close();
|
|
8372
8546
|
this.presence.close();
|
|
@@ -8456,8 +8630,8 @@ class Ditto {
|
|
|
8456
8630
|
}
|
|
8457
8631
|
validateIdentity(identity) {
|
|
8458
8632
|
const validIdentity = { ...identity };
|
|
8459
|
-
|
|
8460
|
-
const appID = identity
|
|
8633
|
+
// @ts-expect-error we validate the existence of the value below.
|
|
8634
|
+
const appID = identity.appID;
|
|
8461
8635
|
if (!['offlinePlayground', 'sharedKey', 'manual', 'onlinePlayground', 'onlineWithAuthentication'].includes(identity.type)) {
|
|
8462
8636
|
throw new Error(`Can't create Ditto instance, unknown identity type: ${identity.type}`);
|
|
8463
8637
|
}
|
|
@@ -8503,7 +8677,7 @@ class Ditto {
|
|
|
8503
8677
|
if (this.isSyncActive && !flag) {
|
|
8504
8678
|
this.keepAlive.release('sync');
|
|
8505
8679
|
}
|
|
8506
|
-
this
|
|
8680
|
+
this._isSyncActive = flag;
|
|
8507
8681
|
const isWebValid = this.isWebValid;
|
|
8508
8682
|
const isX509Valid = this.isX509Valid;
|
|
8509
8683
|
const identity = this.identity;
|
|
@@ -8655,6 +8829,67 @@ class StaticTCPClient {
|
|
|
8655
8829
|
class WebsocketClient {
|
|
8656
8830
|
}
|
|
8657
8831
|
|
|
8832
|
+
//
|
|
8833
|
+
// Copyright © 2023 DittoLive Incorporated. All rights reserved.
|
|
8834
|
+
//
|
|
8835
|
+
/**
|
|
8836
|
+
* Represents single result object.
|
|
8837
|
+
* This API needs to be completed to navigate in the result object.
|
|
8838
|
+
* The result object is retrieved via FFI.dqlResultCBOR(Pointer<FFIDqlResult>).
|
|
8839
|
+
*
|
|
8840
|
+
* Currently experimental.
|
|
8841
|
+
*
|
|
8842
|
+
* @internal
|
|
8843
|
+
*/
|
|
8844
|
+
class ExperimentalDqlResult {
|
|
8845
|
+
get value() {
|
|
8846
|
+
if (this.storedValue === undefined) {
|
|
8847
|
+
const result = Bridge.dqlResult.handleFor(this);
|
|
8848
|
+
const cbor = experimentalDqlResultCBOR(result.deref());
|
|
8849
|
+
this.storedValue = CBOR.decode(cbor);
|
|
8850
|
+
}
|
|
8851
|
+
return this.storedValue;
|
|
8852
|
+
}
|
|
8853
|
+
/**
|
|
8854
|
+
* FIXME: warn users who try to instantiate this class themselves
|
|
8855
|
+
*
|
|
8856
|
+
* @internal
|
|
8857
|
+
*/
|
|
8858
|
+
constructor() { }
|
|
8859
|
+
}
|
|
8860
|
+
|
|
8861
|
+
//
|
|
8862
|
+
// Copyright © 2023 DittoLive Incorporated. All rights reserved.
|
|
8863
|
+
//
|
|
8864
|
+
/**
|
|
8865
|
+
* Represents the response from executing DQL statements.
|
|
8866
|
+
* Currently experimental.
|
|
8867
|
+
*
|
|
8868
|
+
* The memory management is quite complex. Every time when Rust is called
|
|
8869
|
+
* it will clone the result object. Rust mirror of DqlResponse contains
|
|
8870
|
+
* the collection of result objects. During the getting results call
|
|
8871
|
+
* Rust will copy DqlResult obejcts, thus JS here gets complete control
|
|
8872
|
+
* of their lifetimes.
|
|
8873
|
+
*
|
|
8874
|
+
* @internal
|
|
8875
|
+
*/
|
|
8876
|
+
class ExperimentalDqlResponse {
|
|
8877
|
+
get results() {
|
|
8878
|
+
if (this.storedResults === undefined) {
|
|
8879
|
+
const response = Bridge.dqlResponse.handleFor(this);
|
|
8880
|
+
const results = experimentalDqlResponseResults(response.deref());
|
|
8881
|
+
this.storedResults = results.map((r) => Bridge.dqlResult.bridge(r));
|
|
8882
|
+
}
|
|
8883
|
+
return this.storedResults;
|
|
8884
|
+
}
|
|
8885
|
+
/**
|
|
8886
|
+
* FIXME: warn users who try to instantiate this class themselves
|
|
8887
|
+
*
|
|
8888
|
+
* @internal
|
|
8889
|
+
*/
|
|
8890
|
+
constructor() { }
|
|
8891
|
+
}
|
|
8892
|
+
|
|
8658
8893
|
//
|
|
8659
8894
|
// Copyright © 2021 DittoLive Incorporated. All rights reserved.
|
|
8660
8895
|
//
|
|
@@ -8666,6 +8901,8 @@ class WebsocketClient {
|
|
|
8666
8901
|
// immediately require the bridged type, oftentimes leading to an import cycle.
|
|
8667
8902
|
Bridge.attachment.registerType(Attachment);
|
|
8668
8903
|
Bridge.document.registerType(Document);
|
|
8904
|
+
Bridge.dqlResult.registerType(ExperimentalDqlResult);
|
|
8905
|
+
Bridge.dqlResponse.registerType(ExperimentalDqlResponse);
|
|
8669
8906
|
Bridge.mutableDocument.registerType(MutableDocument);
|
|
8670
8907
|
Bridge.staticTCPClient.registerType(StaticTCPClient);
|
|
8671
8908
|
Bridge.websocketClient.registerType(WebsocketClient);
|