entangld 2.2.0 → 2.3.0

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 CHANGED
@@ -179,6 +179,15 @@ If these two issues can be resolved at some point, _deref_mode will probably be
179
179
  ## Classes
180
180
 
181
181
  <dl>
182
+ <dt><a href="#Entangld">Entangld</a> ⇐ <code>EventEmitter</code></dt>
183
+ <dd><p>Synchronized Event Store</p>
184
+ </dd>
185
+ <dt><a href="#EntangldError">EntangldError</a></dt>
186
+ <dd><p>Error class for Entangld.</p>
187
+ </dd>
188
+ <dt><a href="#RPCError">RPCError</a></dt>
189
+ <dd><p>Remote Error class for Entangld.</p>
190
+ </dd>
182
191
  <dt><a href="#Entangld_Message">Entangld_Message</a></dt>
183
192
  <dd><p>Message class for Entangld.</p>
184
193
  <p>These messages are used for executing datastore operations between
@@ -204,621 +213,679 @@ callback functions to be trigger properly, and for unsubscribe messages to
204
213
  propogate both directions. <code>set</code>/<code>push</code> messages do not use the <code>.uuid</code> attribute
205
214
  since they require no response.</p>
206
215
  </dd>
207
- <dt><a href="#EntangldError">EntangldError</a></dt>
208
- <dd><p>Error class for Entangld.</p>
209
- </dd>
210
216
  <dt><a href="#Subscription">Subscription</a></dt>
211
217
  <dd><p>A datastore subscription object</p>
212
218
  </dd>
213
- <dt><a href="#Entangld">Entangld</a> ⇐ <code>EventEmitter</code></dt>
214
- <dd><p>Synchronized Event Store</p>
215
- </dd>
216
219
  </dl>
217
220
 
218
- <a name="Entangld_Message"></a>
219
-
220
- ## Entangld\_Message
221
- Message class for Entangld.
222
-
223
- These messages are used for executing datastore operations between
224
- remote datastores. In these relationships, there is always an upstream
225
- and downstream pair, so that `get`, `set`, `push` and `subscribe` messages
226
- are created upstream and passed downstream while `event` and `value` messages
227
- are created downstream and are passed back up. `unsubscribe` events can travel
228
- in both directions. To maintain consistency, the internal `.path` attribute
229
- will always refer a path relative to the downstream datastore, since the
230
- downstream datastores do not necessarilly have access to the upstream store
231
- structure, and so cannot generally construct upstream paths. This means that
232
- the `.path` attribute is a `tree` relative to the upstream datastore, and
233
- the upstream path can be reconstructed as:
234
- ```javascript
235
- > upstream._namespaces.get(downstream) + "." + msg.path;
236
- ```
237
- Since `unsubscribe` messages can pass either upstream or downstream, the notion
238
- of a path is ill-defined, and so unsubscribe messages should have their `.path`
239
- attributes set to undefined or null.
221
+ <a name="Entangld"></a>
240
222
 
241
- Most messages will also have a `.uuid` attribute. For `get`/`value` messages,
242
- this allows for the value to be properly linked back up with the original `get`
243
- message. For the `subscribe`/`unsubscribe`/`event` messages, this allows for
244
- callback functions to be trigger properly, and for unsubscribe messages to
245
- propogate both directions. `set`/`push` messages do not use the `.uuid` attribute
246
- since they require no response.
223
+ ## Entangld ⇐ <code>EventEmitter</code>
224
+ Synchronized Event Store
247
225
 
248
226
  **Kind**: global class
227
+ **Extends**: <code>EventEmitter</code>
249
228
 
250
- * [Entangld_Message](#Entangld_Message)
251
- * [.get(tree, [get_params])](#Entangld_Message.get) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
252
- * [.value(get_msg, value)](#Entangld_Message.value) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
253
- * [.setpush(obj)](#Entangld_Message.setpush) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
254
- * [.subscribe(tree, uuid)](#Entangld_Message.subscribe) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
255
- * [.event(path, value, uuid)](#Entangld_Message.event) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
256
- * [.unsubscribe(uuid)](#Entangld_Message.unsubscribe)
229
+ * [Entangld](#Entangld) ⇐ <code>EventEmitter</code>
230
+ * [.namespaces](#Entangld+namespaces) ⇒ <code>array</code>
231
+ * [.subscriptions](#Entangld+subscriptions) ⇒ [<code>Array.&lt;Subscription&gt;</code>](#Subscription)
232
+ * [.namespace()](#Entangld+namespace) ⇒ <code>string</code>
233
+ * [.attach(namespace, obj)](#Entangld+attach)
234
+ * [.detach([namespace], [obj])](#Entangld+detach) ⇒ <code>boolean</code>
235
+ * [.transmit(func)](#Entangld+transmit)
236
+ * [.receive(msg, obj)](#Entangld+receive)
237
+ * [.push(path, data, [limit])](#Entangld+push)
238
+ * [.set(path, data, [operation_type], [params])](#Entangld+set)
239
+ * [.set_rpc(path, func, opts)](#Entangld+set_rpc)
240
+ * [.set_rpc_class(object, key_description_pairs, opts)](#Entangld+set_rpc_class)
241
+ * [.call_rpc(path, [args])](#Entangld+call_rpc) ⇒ <code>Promise</code>
242
+ * [.get(path, [params])](#Entangld+get) ⇒ <code>Promise</code>
243
+ * [.subscribe(path, func, [every])](#Entangld+subscribe) ⇒ <code>uuidv4</code>
244
+ * [.subscribed_to(subscription)](#Entangld+subscribed_to) ⇒ <code>Boolean</code>
245
+ * [.unsubscribe(path_or_uuid)](#Entangld+unsubscribe) ⇒ <code>number</code>
246
+ * [.unsubscribe_tree(path)](#Entangld+unsubscribe_tree)
257
247
 
258
- <a name="Entangld_Message.get"></a>
248
+ <a name="Entangld+namespaces"></a>
259
249
 
260
- ### Entangld_Message.get(tree, [get_params]) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
261
- Create a `get` message for remote datastores
250
+ ### entangld.namespaces ⇒ <code>array</code>
251
+ Get namespaces
262
252
 
263
- **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
264
- **Returns**: [<code>Entangld\_Message</code>](#Entangld_Message) - - The get message to pass to the remote datastore
253
+ **Kind**: instance property of [<code>Entangld</code>](#Entangld)
254
+ **Returns**: <code>array</code> - namespaces - an array of attached namespaces
255
+ **Read only**: true
256
+ <a name="Entangld+subscriptions"></a>
265
257
 
266
- | Param | Type | Description |
267
- | --- | --- | --- |
268
- | tree | <code>string</code> | the path relative to the remote datastore |
269
- | [get_params] | <code>\*</code> | any parameters to be passed to the remote datastore's local get function |
258
+ ### entangld.subscriptions ⇒ [<code>Array.&lt;Subscription&gt;</code>](#Subscription)
259
+ Get list of subscriptions associated with this object
270
260
 
271
- <a name="Entangld_Message.value"></a>
261
+ Note, this will include `head`, `terminal` and `pass through` subscriptions,
262
+ which can be checked using getter methods of the subscription object.
272
263
 
273
- ### Entangld_Message.value(get_msg, value) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
274
- Create a `value` message in response to a `get` message
264
+ **Kind**: instance property of [<code>Entangld</code>](#Entangld)
265
+ **Returns**: [<code>Array.&lt;Subscription&gt;</code>](#Subscription) - array of Subscriptions associated with this object
266
+ **Read only**: true
267
+ <a name="Entangld+namespace"></a>
275
268
 
276
- **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
277
- **Returns**: [<code>Entangld\_Message</code>](#Entangld_Message) - - The `value` message to pass back
269
+ ### entangld.namespace() ⇒ <code>string</code>
270
+ Get namespace for a store
278
271
 
279
- | Param | Type | Description |
280
- | --- | --- | --- |
281
- | get_msg | [<code>Entangld\_Message</code>](#Entangld_Message) | the `get` message which this is in response to |
282
- | value | | the value of the `get` |
272
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
273
+ **Returns**: <code>string</code> - namespace for the given store
274
+ **Read only**: true
275
+ <a name="Entangld+attach"></a>
283
276
 
284
- <a name="Entangld_Message.setpush"></a>
277
+ ### entangld.attach(namespace, obj)
278
+ Attach a namespace and a store
285
279
 
286
- ### Entangld_Message.setpush(obj) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
287
- Create a `set`/`push` message for a remote datastore
280
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
281
+ **Throws**:
282
+
283
+ - <code>TypeError</code> if namespace/obj is null or empty.
284
+ - [<code>EntangldError</code>](#EntangldError) if you try to attach to the same namespace twice.
288
285
 
289
- **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
290
- **Returns**: [<code>Entangld\_Message</code>](#Entangld_Message) - - the "set" or "push" message
291
286
 
292
287
  | Param | Type | Description |
293
288
  | --- | --- | --- |
294
- | obj | <code>Object</code> | The parameter object for the set/push |
295
- | obj.type | <code>string</code> | either "set" or "push" |
296
- | obj.tree | <code>string</code> | the path (relative to the downstream datastore) |
297
- | obj.value | <code>\*</code> | the value to insert into the datastore |
298
- | obj.params | <code>\*</code> | any additional parameters |
299
-
300
- <a name="Entangld_Message.subscribe"></a>
289
+ | namespace | <code>string</code> | a namespace for this store. |
290
+ | obj | <code>object</code> | an object that will be sent along with "transmit" callbacks when we need something from this store. |
301
291
 
302
- ### Entangld_Message.subscribe(tree, uuid) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
303
- Construct subscribe message
292
+ <a name="Entangld+detach"></a>
304
293
 
305
- **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
306
- **Returns**: [<code>Entangld\_Message</code>](#Entangld_Message) - the `subscribe` message
294
+ ### entangld.detach([namespace], [obj]) ⇒ <code>boolean</code>
295
+ Detach a namespace / obj pair.
307
296
 
308
- | Param | Type | Description |
309
- | --- | --- | --- |
310
- | tree | <code>string</code> | the path (relative to the downstream datastore) |
311
- | uuid | <code>uuidv4</code> | the subscription uuid |
297
+ If you only pass a namespace or a store, it will find the missing item
298
+ before detaching.
312
299
 
313
- <a name="Entangld_Message.event"></a>
300
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
301
+ **Returns**: <code>boolean</code> - true if the element existed and was removed.
302
+ **Throws**:
314
303
 
315
- ### Entangld_Message.event(path, value, uuid) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
316
- Create an `event` message to return data to subscribe callbacks
304
+ - [<code>EntangldError</code>](#EntangldError) Error will be thrown if you don't pass at least
305
+ one parameter.
317
306
 
318
- **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
319
- **Returns**: [<code>Entangld\_Message</code>](#Entangld_Message) - the `event` message
320
307
 
321
308
  | Param | Type | Description |
322
309
  | --- | --- | --- |
323
- | path | <code>string</code> | the path (relative to the downstream store) |
324
- | value | <code>\*</code> | the updated datastore value at the path |
325
- | uuid | <code>uuidv4</code> | the uuid of the subscribe being triggered |
310
+ | [namespace] | <code>string</code> | the namespace. |
311
+ | [obj] | <code>object</code> | the store object. |
326
312
 
327
- <a name="Entangld_Message.unsubscribe"></a>
313
+ <a name="Entangld+transmit"></a>
328
314
 
329
- ### Entangld_Message.unsubscribe(uuid)
330
- Create an unsubscribe message for a subscription uuid
315
+ ### entangld.transmit(func)
316
+ Transmit
331
317
 
332
- **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
318
+ Specify a callback to be used so we can transmit data to another store.
319
+ Callback will be passed (message, obj) where 'message' is an
320
+ Entangld_Message object and obj is the object provided by attach().
333
321
 
334
- | Param | Type | Description |
335
- | --- | --- | --- |
336
- | uuid | <code>String</code> | the subscription uuid |
322
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
323
+ **Throws**:
337
324
 
338
- <a name="EntangldError"></a>
325
+ - <code>TypeError</code> if func is not a function.
339
326
 
340
- ## EntangldError
341
- Error class for Entangld.
342
327
 
343
- **Kind**: global class
344
- <a name="Subscription"></a>
328
+ | Param | Type | Description |
329
+ | --- | --- | --- |
330
+ | func | <code>function</code> | the callback function. |
345
331
 
346
- ## Subscription
347
- A datastore subscription object
332
+ <a name="Entangld+receive"></a>
348
333
 
349
- **Kind**: global class
334
+ ### entangld.receive(msg, obj)
335
+ Receive
350
336
 
351
- * [Subscription](#Subscription)
352
- * [new Subscription(obj)](#new_Subscription_new)
353
- * [.is_pass_through](#Subscription+is_pass_through) ⇒ <code>Boolean</code>
354
- * [.is_terminal](#Subscription+is_terminal) ⇒ <code>Boolean</code>
355
- * [.is_head](#Subscription+is_head) ⇒ <code>Boolean</code>
356
- * [.has_downstream](#Subscription+has_downstream) ⇒ <code>Boolean</code>
357
- * [.has_upstream](#Subscription+has_upstream) ⇒ <code>Boolean</code>
358
- * [.call()](#Subscription+call)
359
- * [.matches_subscription(sub)](#Subscription+matches_subscription) ⇒ <code>Boolean</code>
360
- * [.matches_event_message(msg)](#Subscription+matches_event_message) ⇒ <code>Boolean</code>
361
- * [.matches_unsubscribe_message(msg)](#Subscription+matches_unsubscribe_message) ⇒ <code>Boolean</code>
362
- * [.matches_path(path)](#Subscription+matches_path) ⇒ <code>Boolean</code>
363
- * [.matches_uuid(uuid)](#Subscription+matches_uuid) ⇒ <code>Boolean</code>
364
- * [.is_beneath(path)](#Subscription+is_beneath) ⇒ <code>Boolean</code>
365
- * [.is_above(path)](#Subscription+is_above) ⇒ <code>Boolean</code>
366
- * [.static_copy()](#Subscription+static_copy) ⇒ [<code>Subscription</code>](#Subscription)
337
+ Call this function with the data that was sent via the transmit()
338
+ callback.
367
339
 
368
- <a name="new_Subscription_new"></a>
340
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
341
+ **Throws**:
369
342
 
370
- ### new Subscription(obj)
371
- Constructor
343
+ - <code>ReferenceError</code> if event object was not provided.
344
+ - [<code>EntangldError</code>](#EntangldError) if an unknown message type was received.
372
345
 
373
- **Returns**: [<code>Subscription</code>](#Subscription) - - the subscription object
374
346
 
375
347
  | Param | Type | Description |
376
348
  | --- | --- | --- |
377
- | obj | <code>Object</code> | the configuration object |
378
- | obj.path | <code>string</code> | the datastore path (relative to this datastore) of the subscription |
379
- | obj.uuid | <code>uuidv4</code> | the uuid of the subscription chain |
380
- | obj.callback | <code>function</code> | the callback function, with signature (path, value), where path is relative to this datastore |
381
- | obj.downstream | [<code>Entangld</code>](#Entangld) \| <code>null</code> | the downstream datastore (if any) associated with this subscription |
382
- | obj.upstream | [<code>Entangld</code>](#Entangld) \| <code>null</code> | the upstream datastore (if any) associated with this subscription |
383
- | obj.every | <code>number</code> \| <code>null</code> | how many `set` messages to wait before calling callback |
349
+ | msg | [<code>Entangld\_Message</code>](#Entangld_Message) | the message to process. |
350
+ | obj | <code>object</code> | the attach() object where the message originted. |
384
351
 
385
- <a name="Subscription+is_pass_through"></a>
352
+ <a name="Entangld+push"></a>
386
353
 
387
- ### subscription.is\_pass\_through ⇒ <code>Boolean</code>
388
- Check if subscription is a `pass through` type
354
+ ### entangld.push(path, data, [limit])
355
+ Push an object into an array in the store.
389
356
 
390
- Pass throughs are as the links in a chain of subscriptions to allows
391
- subscriptions to remote datastores. One store acts as the `head`, where
392
- the callback function is registered, an all others are `path through` datastores
393
- which simply pass event messages back up to the head subscription.
357
+ Convenience method for set(path, o, "push").
394
358
 
395
- **Kind**: instance property of [<code>Subscription</code>](#Subscription)
396
- <a name="Subscription+is_terminal"></a>
359
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
360
+ **Throws**:
397
361
 
398
- ### subscription.is\_terminal ⇒ <code>Boolean</code>
399
- Check if this subscription will be directly given data by a datastore
362
+ - <code>TypeError</code> if path is not a string.
400
363
 
401
- **Kind**: instance property of [<code>Subscription</code>](#Subscription)
402
- <a name="Subscription+is_head"></a>
403
364
 
404
- ### subscription.is\_head ⇒ <code>Boolean</code>
405
- Check if this subscription will apply a user-supplied callback to data
365
+ | Param | Type | Default | Description |
366
+ | --- | --- | --- | --- |
367
+ | path | <code>string</code> | | the path to set (like "system.fan.voltage"). |
368
+ | data | <code>object</code> | | the object or function you want to store at path. |
369
+ | [limit] | <code>number</code> | <code></code> | maximum size of the array. Older entries will be removed until the array size is less than or equal to limit. |
406
370
 
407
- **Kind**: instance property of [<code>Subscription</code>](#Subscription)
408
- <a name="Subscription+has_downstream"></a>
371
+ <a name="Entangld+set"></a>
409
372
 
410
- ### subscription.has\_downstream ⇒ <code>Boolean</code>
411
- Check if subscription has any downstream subscriptions
373
+ ### entangld.set(path, data, [operation_type], [params])
374
+ Set an object into the store
412
375
 
413
- It the subscription refers to a remote datastore (the downstream), this
414
- getter will return a true. Note that !this.has_downstream will check if
415
- the subscription is the `tail` subscription object in a subscription chain.
416
-
417
- **Kind**: instance property of [<code>Subscription</code>](#Subscription)
418
- <a name="Subscription+has_upstream"></a>
419
-
420
- ### subscription.has\_upstream ⇒ <code>Boolean</code>
421
- Check if subscription has any upstream subscriptions
422
-
423
- It the subscription passes data back to a remote datastore (the upstream), this
424
- getter will return a true.
376
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
377
+ **Throws**:
425
378
 
426
- **Kind**: instance property of [<code>Subscription</code>](#Subscription)
427
- <a name="Subscription+call"></a>
379
+ - <code>TypeError</code> if path is not a string.
428
380
 
429
- ### subscription.call()
430
- Apply this callback function
431
381
 
432
- Note, this method also tracks the number of times that a callback
433
- function is called (if this subscription is terminal), so that if
434
- the subscriptions are throttled by specifying an `this.every`,
435
- this method will only call the callback function every `this.every`
436
- times it receives a `set` message. If this subscription is not
437
- terminal, then the callback function is called every time.
382
+ | Param | Type | Default | Description |
383
+ | --- | --- | --- | --- |
384
+ | path | <code>string</code> | | the path to set (like "system.fan.voltage"). |
385
+ | data | <code>object</code> | | the object or function you want to store at path. |
386
+ | [operation_type] | <code>string</code> | <code>&quot;\&quot;set\&quot;&quot;</code> | whether to set or push the new data (push only works if the data item exists and is an array). |
387
+ | [params] | <code>object</code> | | additional parameters. |
438
388
 
439
- This method also is safed when a callback function is not give (i.e.
440
- by the `this.static_copy()` method).
389
+ <a name="Entangld+set_rpc"></a>
441
390
 
442
- **Kind**: instance method of [<code>Subscription</code>](#Subscription)
443
- <a name="Subscription+matches_subscription"></a>
391
+ ### entangld.set\_rpc(path, func, opts)
392
+ Set a function as an RPC in the datastore
444
393
 
445
- ### subscription.matches\_subscription(sub) ⇒ <code>Boolean</code>
446
- Check if a different `Subscription` object matches this subscription
394
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
395
+ **Throws**:
447
396
 
448
- **Kind**: instance method of [<code>Subscription</code>](#Subscription)
449
- **Returns**: <code>Boolean</code> - - True if the subscriptions match
397
+ - <code>TypeError</code> if path is not a string.
450
398
 
451
- | Param | Type | Description |
452
- | --- | --- | --- |
453
- | sub | [<code>Subscription</code>](#Subscription) | a different subscription |
454
399
 
455
- <a name="Subscription+matches_event_message"></a>
400
+ | Param | Type | Default | Description |
401
+ | --- | --- | --- | --- |
402
+ | path | <code>string</code> | | the path to set (like "system.fan.voltage"). |
403
+ | func | <code>function</code> | | the function you want to store at path. |
404
+ | opts | <code>object</code> | | |
405
+ | [opts.description] | <code>string</code> | <code>null</code> | description for the function |
406
+ | [opts.function_string] | <code>string</code> | <code>null</code> | optional string of function source code to pass to parameter_parser |
456
407
 
457
- ### subscription.matches\_event\_message(msg) ⇒ <code>Boolean</code>
458
- Check if an `event` message matches this subscription
408
+ <a name="Entangld+set_rpc_class"></a>
459
409
 
460
- **Kind**: instance method of [<code>Subscription</code>](#Subscription)
461
- **Returns**: <code>Boolean</code> - - True if the message is associated with the subscription
410
+ ### entangld.set\_rpc\_class(object, key_description_pairs, opts)
411
+ Set a class instance as an RPC object in the datastore
462
412
 
463
- | Param | Type | Description |
464
- | --- | --- | --- |
465
- | msg | [<code>Entangld\_Message</code>](#Entangld_Message) | a received message from a downstream datastore |
413
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
414
+ **Throws**:
466
415
 
467
- <a name="Subscription+matches_unsubscribe_message"></a>
416
+ - <code>TypeError</code> if path is not a string.
468
417
 
469
- ### subscription.matches\_unsubscribe\_message(msg) ⇒ <code>Boolean</code>
470
- Check if an `unsubscribe` message matches this subscription
471
418
 
472
- **Kind**: instance method of [<code>Subscription</code>](#Subscription)
473
- **Returns**: <code>Boolean</code> - - True if the message is associated with the subscription
419
+ | Param | Type | Default | Description |
420
+ | --- | --- | --- | --- |
421
+ | object | <code>\*</code> | | The object to attach |
422
+ | key_description_pairs | <code>Array</code> | | An array of key, description pairs |
423
+ | opts | <code>object</code> | | |
424
+ | [opts.description] | <code>string</code> | <code>null</code> | description for the function |
425
+ | [opts.function_string] | <code>string</code> | <code>null</code> | optional string of function source code to pass to parameter_parser |
474
426
 
475
- | Param | Type | Description |
476
- | --- | --- | --- |
477
- | msg | [<code>Entangld\_Message</code>](#Entangld_Message) | a received message from a downstream datastore |
427
+ <a name="Entangld+call_rpc"></a>
478
428
 
479
- <a name="Subscription+matches_path"></a>
429
+ ### entangld.call\_rpc(path, [args]) ⇒ <code>Promise</code>
430
+ Call an RPC procedure in the datastore
480
431
 
481
- ### subscription.matches\_path(path) ⇒ <code>Boolean</code>
482
- Check if a provided path matches this path
432
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
433
+ **Returns**: <code>Promise</code> - promise resolving to return value of the rpc
434
+ **Throws**:
483
435
 
484
- **Kind**: instance method of [<code>Subscription</code>](#Subscription)
485
- **Returns**: <code>Boolean</code> - - true if the path matches
436
+ - [<code>RPCError</code>](#RPCError) if the rpc call experienced an error
486
437
 
487
- | Param | Type | Description |
488
- | --- | --- | --- |
489
- | path | <code>String</code> | a path string to check against |
490
438
 
491
- <a name="Subscription+matches_uuid"></a>
439
+ | Param | Type | Default | Description |
440
+ | --- | --- | --- | --- |
441
+ | path | <code>string</code> | | the path to query (like "system.voltage"). |
442
+ | [args] | <code>Array</code> | <code>[]</code> | the arguments to pass to the RPC. |
492
443
 
493
- ### subscription.matches\_uuid(uuid) ⇒ <code>Boolean</code>
494
- Check if a provided uuid matches this uuid
444
+ <a name="Entangld+get"></a>
495
445
 
496
- **Kind**: instance method of [<code>Subscription</code>](#Subscription)
497
- **Returns**: <code>Boolean</code> - - true if the path matches
446
+ ### entangld.get(path, [params]) ⇒ <code>Promise</code>
447
+ Get an object from the store.
498
448
 
499
- | Param | Type | Description |
500
- | --- | --- | --- |
501
- | uuid | <code>uuidv4</code> | a uuid string to check against |
449
+ Note: using max_depth, especially large max_depth, involves a lot of
450
+ recursion and may be expensive.
502
451
 
503
- <a name="Subscription+is_beneath"></a>
452
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
453
+ **Returns**: <code>Promise</code> - promise resolving to the object at that path.
454
+ **Throws**:
504
455
 
505
- ### subscription.is\_beneath(path) ⇒ <code>Boolean</code>
506
- Check if subscription path is beneath a provided path
456
+ - <code>TypeError</code> if path is not a string.
507
457
 
508
- **Kind**: instance method of [<code>Subscription</code>](#Subscription)
509
- **Returns**: <code>Boolean</code> - - true if the subscription is beneath the path
510
458
 
511
459
  | Param | Type | Description |
512
460
  | --- | --- | --- |
513
- | path | <code>String</code> | a path string to check against |
514
-
515
- <a name="Subscription+is_above"></a>
516
-
517
- ### subscription.is\_above(path) ⇒ <code>Boolean</code>
518
- Check if subscription path is above a provided path
461
+ | path | <code>string</code> | the path to query (like "system.voltage"). |
462
+ | [params] | <code>object</code> | the parameters to be passed to the remote function (RPC) or the maximum depth of the returned object (normal mode). |
519
463
 
520
- **Kind**: instance method of [<code>Subscription</code>](#Subscription)
521
- **Returns**: <code>Boolean</code> - - true if the subscription is beneath the path
464
+ <a name="Entangld+subscribe"></a>
522
465
 
523
- | Param | Type | Description |
524
- | --- | --- | --- |
525
- | path | <code>String</code> | a path string to check against |
466
+ ### entangld.subscribe(path, func, [every]) ⇒ <code>uuidv4</code>
467
+ Subscribe to change events for a path
526
468
 
527
- <a name="Subscription+static_copy"></a>
469
+ If objects at or below this path change, you will get a callback
528
470
 
529
- ### subscription.static\_copy() ⇒ [<code>Subscription</code>](#Subscription)
530
- Get a copy of this subscription without external references
471
+ Subscriptions to keys within attach()ed stores are remote subscriptions.
472
+ If several stores are attached in some kind of arrangement, a given key
473
+ may actually traverse multiple stores! Since each store only knows its
474
+ immediate neighbors - and has no introspection into those neighbors - each
475
+ store is only able to keeps track of the neighbor on each side with
476
+ respect to a particular path and has no knowledge of the eventual
477
+ endpoints. This means that subscribing across several datstores is accomplished
478
+ by daisy-chaining 2-way subscriptions across each datastore interface.
531
479
 
532
- This creates a copy, except the upstream/downstream references
533
- are set to true (if they exist) or null (if they don't. Addtionally,
534
- the callback function is excluded.
480
+ For example, let's suppose capital letters represent Entangld stores and
481
+ lowercase letters are actual objects. Then the path "A.B.c.d.E.F.g.h"
482
+ will represent a subscription that traverses four Entangld stores.
483
+ From the point of view of a store in the middle - say, E - the "upstream"
484
+ is B and the "downstream" is F.
535
485
 
536
- **Kind**: instance method of [<code>Subscription</code>](#Subscription)
537
- **Returns**: [<code>Subscription</code>](#Subscription) - a copy of this subscription object
538
- <a name="Entangld"></a>
486
+ Each store involved keeps track of any subscriptions with which it is
487
+ involved. It tracks the upstream and downstream, and the uuid of the
488
+ subscription. The uuid is the same across all stores for a given
489
+ subscription. For a particular store, the upstream is null if it is the
490
+ original link in the chain (called the `head`), and the downstream is
491
+ null if this store owns the endpoint value (called the `tail`). Any
492
+ subscription which is not the head of a chain is called a `pass through`
493
+ subscription, because it exist only to pass `event` messages back up the
494
+ chain to the head (where the user-provided callback function exists).
495
+ subscriptions can be checked to see if they are `pass through` type via
496
+ the getter `sub.is_pass_through`.
539
497
 
540
- ## Entangld ⇐ <code>EventEmitter</code>
541
- Synchronized Event Store
498
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
499
+ **Returns**: <code>uuidv4</code> - - the uuid of the subscription
500
+ **Throws**:
542
501
 
543
- **Kind**: global class
544
- **Extends**: <code>EventEmitter</code>
502
+ - <code>TypeError</code> if path is not a string.
545
503
 
546
- * [Entangld](#Entangld) ⇐ <code>EventEmitter</code>
547
- * [.namespaces](#Entangld+namespaces) ⇒ <code>array</code>
548
- * [.subscriptions](#Entangld+subscriptions) ⇒ [<code>Array.&lt;Subscription&gt;</code>](#Subscription)
549
- * [.namespace()](#Entangld+namespace) ⇒ <code>string</code>
550
- * [.attach(namespace, obj)](#Entangld+attach)
551
- * [.detach([namespace], [obj])](#Entangld+detach) ⇒ <code>boolean</code>
552
- * [.transmit(func)](#Entangld+transmit)
553
- * [.receive(msg, obj)](#Entangld+receive)
554
- * [.push(path, data, [limit])](#Entangld+push)
555
- * [.set(path, data, [operation_type], [params])](#Entangld+set)
556
- * [.get(path, [params])](#Entangld+get) ⇒ <code>Promise</code>
557
- * [.subscribe(path, func, [every])](#Entangld+subscribe) ⇒ <code>uuidv4</code>
558
- * [.subscribed_to(subscription)](#Entangld+subscribed_to) ⇒ <code>Boolean</code>
559
- * [.unsubscribe(path_or_uuid)](#Entangld+unsubscribe) ⇒ <code>number</code>
560
- * [.unsubscribe_tree(path)](#Entangld+unsubscribe_tree)
561
504
 
562
- <a name="Entangld+namespaces"></a>
505
+ | Param | Type | Default | Description |
506
+ | --- | --- | --- | --- |
507
+ | path | <code>string</code> | | the path to watch. Use of '*' is allowed as a wildcard (e.g. "system.*") |
508
+ | func | <code>function</code> | | the callback - will be of the form (path, value). |
509
+ | [every] | <code>number</code> \| <code>null</code> | <code></code> | the number of `set` messages to wait before calling callback |
563
510
 
564
- ### entangld.namespaces ⇒ <code>array</code>
565
- Get namespaces
511
+ <a name="Entangld+subscribed_to"></a>
566
512
 
567
- **Kind**: instance property of [<code>Entangld</code>](#Entangld)
568
- **Returns**: <code>array</code> - namespaces - an array of attached namespaces
569
- **Read only**: true
570
- <a name="Entangld+subscriptions"></a>
513
+ ### entangld.subscribed\_to(subscription) ⇒ <code>Boolean</code>
514
+ Check for subscription
571
515
 
572
- ### entangld.subscriptions ⇒ [<code>Array.&lt;Subscription&gt;</code>](#Subscription)
573
- Get list of subscriptions associated with this object
516
+ Are we subscribed to a particular remote path?
574
517
 
575
- Note, this will include `head`, `terminal` and `pass through` subscriptions,
576
- which can be checked using getter methods of the subscription object.
518
+ **Kind**: instance method of [<code>Entangld</code>](#Entangld)
519
+ **Returns**: <code>Boolean</code> - true if we are subscribed.
577
520
 
578
- **Kind**: instance property of [<code>Entangld</code>](#Entangld)
579
- **Returns**: [<code>Array.&lt;Subscription&gt;</code>](#Subscription) - array of Subscriptions associated with this object
580
- **Read only**: true
581
- <a name="Entangld+namespace"></a>
521
+ | Param | Type | Description |
522
+ | --- | --- | --- |
523
+ | subscription | <code>String</code> | the subscription to check for. |
582
524
 
583
- ### entangld.namespace() ⇒ <code>string</code>
584
- Get namespace for a store
525
+ <a name="Entangld+unsubscribe"></a>
585
526
 
586
- **Kind**: instance method of [<code>Entangld</code>](#Entangld)
587
- **Returns**: <code>string</code> - namespace for the given store
588
- **Read only**: true
589
- <a name="Entangld+attach"></a>
527
+ ### entangld.unsubscribe(path_or_uuid) ⇒ <code>number</code>
528
+ Unubscribe to change events for a given path or uuid.
590
529
 
591
- ### entangld.attach(namespace, obj)
592
- Attach a namespace and a store
530
+ Caution - if a path is provided, _all_ events belonging to you with that
531
+ path will be deleted, so if you have multiple subscriptions on a single path,
532
+ and only want one of them to be removed, you must provide the uuid instead.
593
533
 
594
534
  **Kind**: instance method of [<code>Entangld</code>](#Entangld)
535
+ **Returns**: <code>number</code> - count of subscriptions removed.
595
536
  **Throws**:
596
537
 
597
- - <code>TypeError</code> if namespace/obj is null or empty.
598
- - [<code>EntangldError</code>](#EntangldError) if you try to attach to the same namespace twice.
538
+ - [<code>EntangldError</code>](#EntangldError) if no subscriptions were found.
599
539
 
600
540
 
601
541
  | Param | Type | Description |
602
542
  | --- | --- | --- |
603
- | namespace | <code>string</code> | a namespace for this store. |
604
- | obj | <code>object</code> | an object that will be sent along with "transmit" callbacks when we need something from this store. |
543
+ | path_or_uuid | <code>String</code> \| <code>uuidv4</code> | the path (or uuid) to unwatch. |
605
544
 
606
- <a name="Entangld+detach"></a>
545
+ <a name="Entangld+unsubscribe_tree"></a>
607
546
 
608
- ### entangld.detach([namespace], [obj]) ⇒ <code>boolean</code>
609
- Detach a namespace / obj pair.
547
+ ### entangld.unsubscribe\_tree(path)
548
+ Unsubscribe tree.
610
549
 
611
- If you only pass a namespace or a store, it will find the missing item
612
- before detaching.
550
+ Remove any subscriptions that are beneath a path.
613
551
 
614
552
  **Kind**: instance method of [<code>Entangld</code>](#Entangld)
615
- **Returns**: <code>boolean</code> - true if the element existed and was removed.
616
553
  **Throws**:
617
554
 
618
- - [<code>EntangldError</code>](#EntangldError) Error will be thrown if you don't pass at least
619
- one parameter.
555
+ - [<code>EntangldError</code>](#EntangldError) error if there are stores we cannot detach
556
+ (i.e. they belong to someone else / upstream != null)
620
557
 
621
558
 
622
559
  | Param | Type | Description |
623
560
  | --- | --- | --- |
624
- | [namespace] | <code>string</code> | the namespace. |
625
- | [obj] | <code>object</code> | the store object. |
561
+ | path | <code>string</code> | the tree to unwatch. |
626
562
 
627
- <a name="Entangld+transmit"></a>
563
+ <a name="EntangldError"></a>
628
564
 
629
- ### entangld.transmit(func)
630
- Transmit
565
+ ## EntangldError
566
+ Error class for Entangld.
631
567
 
632
- Specify a callback to be used so we can transmit data to another store.
633
- Callback will be passed (message, obj) where 'message' is an
634
- Entangld_Message object and obj is the object provided by attach().
568
+ **Kind**: global class
569
+ <a name="RPCError"></a>
635
570
 
636
- **Kind**: instance method of [<code>Entangld</code>](#Entangld)
637
- **Throws**:
571
+ ## RPCError
572
+ Remote Error class for Entangld.
638
573
 
639
- - <code>TypeError</code> if func is not a function.
574
+ **Kind**: global class
575
+ <a name="Entangld_Message"></a>
640
576
 
577
+ ## Entangld\_Message
578
+ Message class for Entangld.
579
+
580
+ These messages are used for executing datastore operations between
581
+ remote datastores. In these relationships, there is always an upstream
582
+ and downstream pair, so that `get`, `set`, `push` and `subscribe` messages
583
+ are created upstream and passed downstream while `event` and `value` messages
584
+ are created downstream and are passed back up. `unsubscribe` events can travel
585
+ in both directions. To maintain consistency, the internal `.path` attribute
586
+ will always refer a path relative to the downstream datastore, since the
587
+ downstream datastores do not necessarilly have access to the upstream store
588
+ structure, and so cannot generally construct upstream paths. This means that
589
+ the `.path` attribute is a `tree` relative to the upstream datastore, and
590
+ the upstream path can be reconstructed as:
591
+ ```javascript
592
+ > upstream._namespaces.get(downstream) + "." + msg.path;
593
+ ```
594
+ Since `unsubscribe` messages can pass either upstream or downstream, the notion
595
+ of a path is ill-defined, and so unsubscribe messages should have their `.path`
596
+ attributes set to undefined or null.
597
+
598
+ Most messages will also have a `.uuid` attribute. For `get`/`value` messages,
599
+ this allows for the value to be properly linked back up with the original `get`
600
+ message. For the `subscribe`/`unsubscribe`/`event` messages, this allows for
601
+ callback functions to be trigger properly, and for unsubscribe messages to
602
+ propogate both directions. `set`/`push` messages do not use the `.uuid` attribute
603
+ since they require no response.
604
+
605
+ **Kind**: global class
606
+
607
+ * [Entangld_Message](#Entangld_Message)
608
+ * [.get(tree, [get_params])](#Entangld_Message.get) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
609
+ * [.value(get_msg, value)](#Entangld_Message.value) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
610
+ * [.setpush(obj)](#Entangld_Message.setpush) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
611
+ * [.subscribe(tree, uuid)](#Entangld_Message.subscribe) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
612
+ * [.event(path, value, uuid)](#Entangld_Message.event) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
613
+ * [.unsubscribe(uuid)](#Entangld_Message.unsubscribe)
614
+
615
+ <a name="Entangld_Message.get"></a>
616
+
617
+ ### Entangld_Message.get(tree, [get_params]) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
618
+ Create a `get` message for remote datastores
619
+
620
+ **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
621
+ **Returns**: [<code>Entangld\_Message</code>](#Entangld_Message) - - The get message to pass to the remote datastore
641
622
 
642
623
  | Param | Type | Description |
643
624
  | --- | --- | --- |
644
- | func | <code>function</code> | the callback function. |
625
+ | tree | <code>string</code> | the path relative to the remote datastore |
626
+ | [get_params] | <code>\*</code> | any parameters to be passed to the remote datastore's local get function |
645
627
 
646
- <a name="Entangld+receive"></a>
628
+ <a name="Entangld_Message.value"></a>
647
629
 
648
- ### entangld.receive(msg, obj)
649
- Receive
630
+ ### Entangld_Message.value(get_msg, value) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
631
+ Create a `value` message in response to a `get` message
650
632
 
651
- Call this function with the data that was sent via the transmit()
652
- callback.
633
+ **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
634
+ **Returns**: [<code>Entangld\_Message</code>](#Entangld_Message) - - The `value` message to pass back
653
635
 
654
- **Kind**: instance method of [<code>Entangld</code>](#Entangld)
655
- **Throws**:
636
+ | Param | Type | Description |
637
+ | --- | --- | --- |
638
+ | get_msg | [<code>Entangld\_Message</code>](#Entangld_Message) | the `get` message which this is in response to |
639
+ | value | | the value of the `get` |
656
640
 
657
- - <code>ReferenceError</code> if event object was not provided.
658
- - [<code>EntangldError</code>](#EntangldError) if an unknown message type was received.
641
+ <a name="Entangld_Message.setpush"></a>
659
642
 
643
+ ### Entangld_Message.setpush(obj) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
644
+ Create a `set`/`push` message for a remote datastore
645
+
646
+ **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
647
+ **Returns**: [<code>Entangld\_Message</code>](#Entangld_Message) - - the "set" or "push" message
660
648
 
661
649
  | Param | Type | Description |
662
650
  | --- | --- | --- |
663
- | msg | [<code>Entangld\_Message</code>](#Entangld_Message) | the message to process. |
664
- | obj | <code>object</code> | the attach() object where the message originted. |
651
+ | obj | <code>Object</code> | The parameter object for the set/push |
652
+ | obj.type | <code>string</code> | either "set" or "push" |
653
+ | obj.tree | <code>string</code> | the path (relative to the downstream datastore) |
654
+ | obj.value | <code>\*</code> | the value to insert into the datastore |
655
+ | obj.params | <code>\*</code> | any additional parameters |
665
656
 
666
- <a name="Entangld+push"></a>
657
+ <a name="Entangld_Message.subscribe"></a>
667
658
 
668
- ### entangld.push(path, data, [limit])
669
- Push an object into an array in the store.
659
+ ### Entangld_Message.subscribe(tree, uuid) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
660
+ Construct subscribe message
670
661
 
671
- Convenience method for set(path, o, "push").
662
+ **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
663
+ **Returns**: [<code>Entangld\_Message</code>](#Entangld_Message) - the `subscribe` message
672
664
 
673
- **Kind**: instance method of [<code>Entangld</code>](#Entangld)
674
- **Throws**:
665
+ | Param | Type | Description |
666
+ | --- | --- | --- |
667
+ | tree | <code>string</code> | the path (relative to the downstream datastore) |
668
+ | uuid | <code>uuidv4</code> | the subscription uuid |
675
669
 
676
- - <code>TypeError</code> if path is not a string.
670
+ <a name="Entangld_Message.event"></a>
677
671
 
672
+ ### Entangld_Message.event(path, value, uuid) ⇒ [<code>Entangld\_Message</code>](#Entangld_Message)
673
+ Create an `event` message to return data to subscribe callbacks
678
674
 
679
- | Param | Type | Default | Description |
680
- | --- | --- | --- | --- |
681
- | path | <code>string</code> | | the path to set (like "system.fan.voltage"). |
682
- | data | <code>object</code> | | the object or function you want to store at path. |
683
- | [limit] | <code>number</code> | <code></code> | maximum size of the array. Older entries will be removed until the array size is less than or equal to limit. |
675
+ **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
676
+ **Returns**: [<code>Entangld\_Message</code>](#Entangld_Message) - the `event` message
684
677
 
685
- <a name="Entangld+set"></a>
678
+ | Param | Type | Description |
679
+ | --- | --- | --- |
680
+ | path | <code>string</code> | the path (relative to the downstream store) |
681
+ | value | <code>\*</code> | the updated datastore value at the path |
682
+ | uuid | <code>uuidv4</code> | the uuid of the subscribe being triggered |
686
683
 
687
- ### entangld.set(path, data, [operation_type], [params])
688
- Set an object into the store
684
+ <a name="Entangld_Message.unsubscribe"></a>
689
685
 
690
- **Kind**: instance method of [<code>Entangld</code>](#Entangld)
691
- **Throws**:
686
+ ### Entangld_Message.unsubscribe(uuid)
687
+ Create an unsubscribe message for a subscription uuid
692
688
 
693
- - <code>TypeError</code> if path is not a string.
689
+ **Kind**: static method of [<code>Entangld\_Message</code>](#Entangld_Message)
694
690
 
691
+ | Param | Type | Description |
692
+ | --- | --- | --- |
693
+ | uuid | <code>String</code> | the subscription uuid |
695
694
 
696
- | Param | Type | Default | Description |
697
- | --- | --- | --- | --- |
698
- | path | <code>string</code> | | the path to set (like "system.fan.voltage"). |
699
- | data | <code>object</code> | | the object or function you want to store at path. |
700
- | [operation_type] | <code>string</code> | <code>&quot;\&quot;set\&quot;&quot;</code> | whether to set or push the new data (push only works if the data item exists and is an array). |
701
- | [params] | <code>object</code> | | additional parameters. |
695
+ <a name="Subscription"></a>
702
696
 
703
- <a name="Entangld+get"></a>
697
+ ## Subscription
698
+ A datastore subscription object
704
699
 
705
- ### entangld.get(path, [params]) ⇒ <code>Promise</code>
706
- Get an object from the store.
700
+ **Kind**: global class
707
701
 
708
- Note: using max_depth, especially large max_depth, involves a lot of
709
- recursion and may be expensive.
702
+ * [Subscription](#Subscription)
703
+ * [new Subscription(obj)](#new_Subscription_new)
704
+ * [.is_pass_through](#Subscription+is_pass_through) ⇒ <code>Boolean</code>
705
+ * [.is_terminal](#Subscription+is_terminal) ⇒ <code>Boolean</code>
706
+ * [.is_head](#Subscription+is_head) ⇒ <code>Boolean</code>
707
+ * [.has_downstream](#Subscription+has_downstream) ⇒ <code>Boolean</code>
708
+ * [.has_upstream](#Subscription+has_upstream) ⇒ <code>Boolean</code>
709
+ * [.call()](#Subscription+call)
710
+ * [.matches_subscription(sub)](#Subscription+matches_subscription) ⇒ <code>Boolean</code>
711
+ * [.matches_event_message(msg)](#Subscription+matches_event_message) ⇒ <code>Boolean</code>
712
+ * [.matches_unsubscribe_message(msg)](#Subscription+matches_unsubscribe_message) ⇒ <code>Boolean</code>
713
+ * [.matches_path(path)](#Subscription+matches_path) ⇒ <code>Boolean</code>
714
+ * [.matches_uuid(uuid)](#Subscription+matches_uuid) ⇒ <code>Boolean</code>
715
+ * [.is_beneath(path)](#Subscription+is_beneath) ⇒ <code>Boolean</code>
716
+ * [.is_above(path)](#Subscription+is_above) ⇒ <code>Boolean</code>
717
+ * [.static_copy()](#Subscription+static_copy) ⇒ [<code>Subscription</code>](#Subscription)
710
718
 
711
- **Kind**: instance method of [<code>Entangld</code>](#Entangld)
712
- **Returns**: <code>Promise</code> - promise resolving to the object at that path.
713
- **Throws**:
719
+ <a name="new_Subscription_new"></a>
714
720
 
715
- - <code>TypeError</code> if path is not a string.
721
+ ### new Subscription(obj)
722
+ Constructor
716
723
 
724
+ **Returns**: [<code>Subscription</code>](#Subscription) - - the subscription object
717
725
 
718
726
  | Param | Type | Description |
719
727
  | --- | --- | --- |
720
- | path | <code>string</code> | the path to query (like "system.voltage"). |
721
- | [params] | <code>object</code> | the parameters to be passed to the remote function (RPC) or the maximum depth of the returned object (normal mode). |
728
+ | obj | <code>Object</code> | the configuration object |
729
+ | obj.path | <code>string</code> | the datastore path (relative to this datastore) of the subscription |
730
+ | obj.uuid | <code>uuidv4</code> | the uuid of the subscription chain |
731
+ | obj.callback | <code>function</code> | the callback function, with signature (path, value), where path is relative to this datastore |
732
+ | obj.downstream | [<code>Entangld</code>](#Entangld) \| <code>null</code> | the downstream datastore (if any) associated with this subscription |
733
+ | obj.upstream | [<code>Entangld</code>](#Entangld) \| <code>null</code> | the upstream datastore (if any) associated with this subscription |
734
+ | obj.every | <code>number</code> \| <code>null</code> | how many `set` messages to wait before calling callback |
722
735
 
723
- <a name="Entangld+subscribe"></a>
736
+ <a name="Subscription+is_pass_through"></a>
724
737
 
725
- ### entangld.subscribe(path, func, [every]) ⇒ <code>uuidv4</code>
726
- Subscribe to change events for a path
738
+ ### subscription.is\_pass\_through ⇒ <code>Boolean</code>
739
+ Check if subscription is a `pass through` type
727
740
 
728
- If objects at or below this path change, you will get a callback
741
+ Pass throughs are as the links in a chain of subscriptions to allows
742
+ subscriptions to remote datastores. One store acts as the `head`, where
743
+ the callback function is registered, an all others are `path through` datastores
744
+ which simply pass event messages back up to the head subscription.
729
745
 
730
- Subscriptions to keys within attach()ed stores are remote subscriptions.
731
- If several stores are attached in some kind of arrangement, a given key
732
- may actually traverse multiple stores! Since each store only knows its
733
- immediate neighbors - and has no introspection into those neighbors - each
734
- store is only able to keeps track of the neighbor on each side with
735
- respect to a particular path and has no knowledge of the eventual
736
- endpoints. This means that subscribing across several datstores is accomplished
737
- by daisy-chaining 2-way subscriptions across each datastore interface.
746
+ **Kind**: instance property of [<code>Subscription</code>](#Subscription)
747
+ <a name="Subscription+is_terminal"></a>
738
748
 
739
- For example, let's suppose capital letters represent Entangld stores and
740
- lowercase letters are actual objects. Then the path "A.B.c.d.E.F.g.h"
741
- will represent a subscription that traverses four Entangld stores.
742
- From the point of view of a store in the middle - say, E - the "upstream"
743
- is B and the "downstream" is F.
749
+ ### subscription.is\_terminal ⇒ <code>Boolean</code>
750
+ Check if this subscription will be directly given data by a datastore
744
751
 
745
- Each store involved keeps track of any subscriptions with which it is
746
- involved. It tracks the upstream and downstream, and the uuid of the
747
- subscription. The uuid is the same across all stores for a given
748
- subscription. For a particular store, the upstream is null if it is the
749
- original link in the chain (called the `head`), and the downstream is
750
- null if this store owns the endpoint value (called the `tail`). Any
751
- subscription which is not the head of a chain is called a `pass through`
752
- subscription, because it exist only to pass `event` messages back up the
753
- chain to the head (where the user-provided callback function exists).
754
- subscriptions can be checked to see if they are `pass through` type via
755
- the getter `sub.is_pass_through`.
752
+ **Kind**: instance property of [<code>Subscription</code>](#Subscription)
753
+ <a name="Subscription+is_head"></a>
756
754
 
757
- **Kind**: instance method of [<code>Entangld</code>](#Entangld)
758
- **Returns**: <code>uuidv4</code> - - the uuid of the subscription
759
- **Throws**:
755
+ ### subscription.is\_head ⇒ <code>Boolean</code>
756
+ Check if this subscription will apply a user-supplied callback to data
760
757
 
761
- - <code>TypeError</code> if path is not a string.
758
+ **Kind**: instance property of [<code>Subscription</code>](#Subscription)
759
+ <a name="Subscription+has_downstream"></a>
760
+
761
+ ### subscription.has\_downstream ⇒ <code>Boolean</code>
762
+ Check if subscription has any downstream subscriptions
762
763
 
764
+ It the subscription refers to a remote datastore (the downstream), this
765
+ getter will return a true. Note that !this.has_downstream will check if
766
+ the subscription is the `tail` subscription object in a subscription chain.
763
767
 
764
- | Param | Type | Default | Description |
765
- | --- | --- | --- | --- |
766
- | path | <code>string</code> | | the path to watch. Use of '*' is allowed as a wildcard (e.g. "system.*") |
767
- | func | <code>function</code> | | the callback - will be of the form (path, value). |
768
- | [every] | <code>number</code> \| <code>null</code> | <code></code> | the number of `set` messages to wait before calling callback |
768
+ **Kind**: instance property of [<code>Subscription</code>](#Subscription)
769
+ <a name="Subscription+has_upstream"></a>
769
770
 
770
- <a name="Entangld+subscribed_to"></a>
771
+ ### subscription.has\_upstream ⇒ <code>Boolean</code>
772
+ Check if subscription has any upstream subscriptions
771
773
 
772
- ### entangld.subscribed\_to(subscription) ⇒ <code>Boolean</code>
773
- Check for subscription
774
+ It the subscription passes data back to a remote datastore (the upstream), this
775
+ getter will return a true.
774
776
 
775
- Are we subscribed to a particular remote path?
777
+ **Kind**: instance property of [<code>Subscription</code>](#Subscription)
778
+ <a name="Subscription+call"></a>
776
779
 
777
- **Kind**: instance method of [<code>Entangld</code>](#Entangld)
778
- **Returns**: <code>Boolean</code> - true if we are subscribed.
780
+ ### subscription.call()
781
+ Apply this callback function
782
+
783
+ Note, this method also tracks the number of times that a callback
784
+ function is called (if this subscription is terminal), so that if
785
+ the subscriptions are throttled by specifying an `this.every`,
786
+ this method will only call the callback function every `this.every`
787
+ times it receives a `set` message. If this subscription is not
788
+ terminal, then the callback function is called every time.
789
+
790
+ This method also is safed when a callback function is not give (i.e.
791
+ by the `this.static_copy()` method).
792
+
793
+ **Kind**: instance method of [<code>Subscription</code>](#Subscription)
794
+ <a name="Subscription+matches_subscription"></a>
795
+
796
+ ### subscription.matches\_subscription(sub) ⇒ <code>Boolean</code>
797
+ Check if a different `Subscription` object matches this subscription
798
+
799
+ **Kind**: instance method of [<code>Subscription</code>](#Subscription)
800
+ **Returns**: <code>Boolean</code> - - True if the subscriptions match
779
801
 
780
802
  | Param | Type | Description |
781
803
  | --- | --- | --- |
782
- | subscription | <code>String</code> | the subscription to check for. |
804
+ | sub | [<code>Subscription</code>](#Subscription) | a different subscription |
783
805
 
784
- <a name="Entangld+unsubscribe"></a>
806
+ <a name="Subscription+matches_event_message"></a>
785
807
 
786
- ### entangld.unsubscribe(path_or_uuid) ⇒ <code>number</code>
787
- Unubscribe to change events for a given path or uuid.
808
+ ### subscription.matches\_event\_message(msg) ⇒ <code>Boolean</code>
809
+ Check if an `event` message matches this subscription
788
810
 
789
- Caution - if a path is provided, _all_ events belonging to you with that
790
- path will be deleted, so if you have multiple subscriptions on a single path,
791
- and only want one of them to be removed, you must provide the uuid instead.
811
+ **Kind**: instance method of [<code>Subscription</code>](#Subscription)
812
+ **Returns**: <code>Boolean</code> - - True if the message is associated with the subscription
792
813
 
793
- **Kind**: instance method of [<code>Entangld</code>](#Entangld)
794
- **Returns**: <code>number</code> - count of subscriptions removed.
795
- **Throws**:
814
+ | Param | Type | Description |
815
+ | --- | --- | --- |
816
+ | msg | [<code>Entangld\_Message</code>](#Entangld_Message) | a received message from a downstream datastore |
796
817
 
797
- - [<code>EntangldError</code>](#EntangldError) if no subscriptions were found.
818
+ <a name="Subscription+matches_unsubscribe_message"></a>
798
819
 
820
+ ### subscription.matches\_unsubscribe\_message(msg) ⇒ <code>Boolean</code>
821
+ Check if an `unsubscribe` message matches this subscription
822
+
823
+ **Kind**: instance method of [<code>Subscription</code>](#Subscription)
824
+ **Returns**: <code>Boolean</code> - - True if the message is associated with the subscription
799
825
 
800
826
  | Param | Type | Description |
801
827
  | --- | --- | --- |
802
- | path_or_uuid | <code>String</code> \| <code>uuidv4</code> | the path (or uuid) to unwatch. |
828
+ | msg | [<code>Entangld\_Message</code>](#Entangld_Message) | a received message from a downstream datastore |
803
829
 
804
- <a name="Entangld+unsubscribe_tree"></a>
830
+ <a name="Subscription+matches_path"></a>
805
831
 
806
- ### entangld.unsubscribe\_tree(path)
807
- Unsubscribe tree.
832
+ ### subscription.matches\_path(path) ⇒ <code>Boolean</code>
833
+ Check if a provided path matches this path
808
834
 
809
- Remove any subscriptions that are beneath a path.
835
+ **Kind**: instance method of [<code>Subscription</code>](#Subscription)
836
+ **Returns**: <code>Boolean</code> - - true if the path matches
810
837
 
811
- **Kind**: instance method of [<code>Entangld</code>](#Entangld)
812
- **Throws**:
838
+ | Param | Type | Description |
839
+ | --- | --- | --- |
840
+ | path | <code>String</code> | a path string to check against |
813
841
 
814
- - [<code>EntangldError</code>](#EntangldError) error if there are stores we cannot detach
815
- (i.e. they belong to someone else / upstream != null)
842
+ <a name="Subscription+matches_uuid"></a>
816
843
 
844
+ ### subscription.matches\_uuid(uuid) ⇒ <code>Boolean</code>
845
+ Check if a provided uuid matches this uuid
846
+
847
+ **Kind**: instance method of [<code>Subscription</code>](#Subscription)
848
+ **Returns**: <code>Boolean</code> - - true if the path matches
817
849
 
818
850
  | Param | Type | Description |
819
851
  | --- | --- | --- |
820
- | path | <code>string</code> | the tree to unwatch. |
852
+ | uuid | <code>uuidv4</code> | a uuid string to check against |
853
+
854
+ <a name="Subscription+is_beneath"></a>
855
+
856
+ ### subscription.is\_beneath(path) ⇒ <code>Boolean</code>
857
+ Check if subscription path is beneath a provided path
858
+
859
+ **Kind**: instance method of [<code>Subscription</code>](#Subscription)
860
+ **Returns**: <code>Boolean</code> - - true if the subscription is beneath the path
861
+
862
+ | Param | Type | Description |
863
+ | --- | --- | --- |
864
+ | path | <code>String</code> | a path string to check against |
865
+
866
+ <a name="Subscription+is_above"></a>
867
+
868
+ ### subscription.is\_above(path) ⇒ <code>Boolean</code>
869
+ Check if subscription path is above a provided path
870
+
871
+ **Kind**: instance method of [<code>Subscription</code>](#Subscription)
872
+ **Returns**: <code>Boolean</code> - - true if the subscription is beneath the path
873
+
874
+ | Param | Type | Description |
875
+ | --- | --- | --- |
876
+ | path | <code>String</code> | a path string to check against |
821
877
 
878
+ <a name="Subscription+static_copy"></a>
879
+
880
+ ### subscription.static\_copy() ⇒ [<code>Subscription</code>](#Subscription)
881
+ Get a copy of this subscription without external references
882
+
883
+ This creates a copy, except the upstream/downstream references
884
+ are set to true (if they exist) or null (if they don't. Addtionally,
885
+ the callback function is excluded.
886
+
887
+ **Kind**: instance method of [<code>Subscription</code>](#Subscription)
888
+ **Returns**: [<code>Subscription</code>](#Subscription) - a copy of this subscription object
822
889
 
823
890
  ## TODO
824
891
  - Make sure incoming values request store doesn't build up