Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

datom

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

datom - npm Package Compare versions

Comparing version 11.0.0 to 12.0.0

202

lib/main.js
(function() {
'use strict';
var Datom, GUY, MAIN, alert, assign, debug, echo, get_base_types, help, info, inspect, letsfreezethat, letsfreezethat_nofreeze, log, p1, p2, plain, praise, rpr, urge, warn, whisper,
indexOf = [].indexOf;
var Datom, GUY, MAIN, alert, assign, debug, echo, get_base_types, help, info, inspect, letsfreezethat, letsfreezethat_nofreeze, log, matcher_cache, plain, praise, rpr, urge, warn, whisper;

@@ -22,9 +21,4 @@ //###########################################################################################################

//===========================================================================================================
// SELECT
//-----------------------------------------------------------------------------------------------------------
p1 = /^(?<skey>(?<sigil>[<^>\[~\]\x23])(?<key>[^<^>\[~\]\x23]*))$/u; // `\x23` used instead of `\#` which causes syntax error (???)
matcher_cache = new Map();
p2 = /^(?<skey>(?<sigil>[<^>\[~\]\x23])(?<key>[^<^>\[~\]\x23]*))\x23(?<attribute>[^<^>\[~\]\x23]+):(?<value>[^<^>\[~\]\x23]+)$/u; // `\x23` used instead of `\#` which causes syntax error (???)
//===========================================================================================================

@@ -49,4 +43,2 @@ // EXPORT

//---------------------------------------------------------------------------------------------------------
this.is_system = this.is_system.bind(this);
//---------------------------------------------------------------------------------------------------------
this.is_stamped = this.is_stamped.bind(this);

@@ -59,25 +51,4 @@ this.is_fresh = this.is_fresh.bind(this);

//---------------------------------------------------------------------------------------------------------
this._new_datom = this._new_datom.bind(this);
this.new_fresh_datom = this.new_fresh_datom.bind(this);
//---------------------------------------------------------------------------------------------------------
this.fresh_datom = this.fresh_datom.bind(this);
//---------------------------------------------------------------------------------------------------------
this.wrap_datom = this.wrap_datom.bind(this);
//---------------------------------------------------------------------------------------------------------
this.new_single_datom = this.new_single_datom.bind(this);
this.new_open_datom = this.new_open_datom.bind(this);
this.new_close_datom = this.new_close_datom.bind(this);
this.new_system_datom = this.new_system_datom.bind(this);
this.new_text_datom = this.new_text_datom.bind(this);
// @new_flush_datom = -> @new_system_datom 'flush'
//---------------------------------------------------------------------------------------------------------
this.new_warning = this.new_warning.bind(this);
//=========================================================================================================
//---------------------------------------------------------------------------------------------------------
/* TAINT likely to be removed */
this.new_xemitter = this.new_xemitter.bind(this);
//=========================================================================================================
//---------------------------------------------------------------------------------------------------------
this.select = this.select.bind(this);

@@ -90,2 +61,3 @@ // super()

this.thaw = this.LFT.thaw;
GUY.props.hide(this, 'matcher_cache', matcher_cache);
return void 0;

@@ -120,7 +92,7 @@ }

return this.lets(d, function(d) {
var ref1, results, v;
ref1 = assign({}, k, ...P);
var ref, results, v;
ref = assign({}, k, ...P);
results = [];
for (k in ref1) {
v = ref1[k];
for (k in ref) {
v = ref[k];
results.push(d[k] = v);

@@ -139,3 +111,3 @@ }

stamp(d, ...P) {
/* Set the `$stamped` attribute on datom to sigil it as processed. Stamped datoms will not be selected
/* Set the `$stamped` attribute on datom to mark it as processed. Stamped datoms will not be selected
by the `select` method unless tag '#stamped' is used. */

@@ -158,20 +130,15 @@ return this.lets(d, function(d) {

is_system(d) {
/* Return whether datom is a system datom (i.e. whether its `sigil` equals `'~'`). */
return d.$key.match(/^[~\[\]]/);
}
is_stamped(d) {
var ref1;
return (ref1 = d.$stamped) != null ? ref1 : false/* i.e. already processed? */;
var ref;
return (ref = d.$stamped) != null ? ref : false/* i.e. already processed? */;
}
is_fresh(d) {
var ref1;
return (ref1 = d.$fresh) != null ? ref1 : false/* i.e. created within stream? */;
var ref;
return (ref = d.$fresh) != null ? ref : false/* i.e. created within stream? */;
}
is_dirty(d) {
var ref1;
return (ref1 = d.$dirty) != null ? ref1 : false/* i.e. modified? */;
var ref;
return (ref = d.$dirty) != null ? ref : false/* i.e. modified? */;
}

@@ -183,32 +150,8 @@

new_datom($key, $value, ...other) {
/* When `other` contains a key `$`, it is treated as a hint to copy
system-level attributes; if the value of key `$` is a POD that has itself a
key `$`, then a copy of that value is used. This allows to write `new_datom
..., $: d` to copy system-level attributes such as source locations to a new
datom. */
new_datom($key, ...P) {
this.types.validate.datom_key($key);
return this._new_datom($key, $value, ...other);
return this.freeze(assign({}, ...P, {$key}));
}
_new_datom($key, $value, ...other) {
var R;
if ($value != null) {
if ((!this.cfg.merge_values) || (!this.types.isa.object($value))) {
$value = {$value};
}
if (indexOf.call(Object.keys($value), '$key') >= 0) {
throw new Error("µ55632 value must not have attribute '$key'");
}
R = assign({}, $value, ...other, {$key});
} else {
R = assign({}, ...other, {$key});
}
while ((this.types.isa.object(R.$)) && (this.types.isa.object(R.$.$))) {
R.$ = this.LFT._deep_copy(R.$.$);
}
return this.freeze(R);
}
fresh_datom(...P) {
new_fresh_datom(...P) {
return this.new_datom(...P, {

@@ -219,47 +162,25 @@ $fresh: true

wrap_datom($key, $value) {
this.types.validate.datom_key($key);
this.types.validate.datom_datom($value);
return this.freeze({$key, $value});
}
//=========================================================================================================
new_single_datom(name, ...P) {
this.types.validate.datom_name(name);
return this._new_datom(`^${name}`, ...P);
//---------------------------------------------------------------------------------------------------------
_get_matcher(selector) {
var R, re;
if ((R = matcher_cache.get(selector)) != null) {
/* TAINT might make this method part of API */
return R;
}
selector = selector.replace(/(?<!\\)\?/g, '.?');
selector = selector.replace(/(?<!\\)\*/g, '.*');
selector = `^(?:${selector})$`;
re = new RegExp(selector, 'u');
R = function(x) {
return re.test(x);
};
matcher_cache.set(selector, R);
return R;
}
new_open_datom(name, ...P) {
this.types.validate.datom_name(name);
return this.new_datom(`<${name}`, ...P);
}
new_close_datom(name, ...P) {
this.types.validate.datom_name(name);
return this.new_datom(`>${name}`, ...P);
}
new_system_datom(name, ...P) {
this.types.validate.datom_name(name);
return this.new_datom(`~${name}`, ...P);
}
new_text_datom(...P) {
return this.new_single_datom('text', ...P);
}
new_end_datom() {
return this.new_system_datom('end');
}
new_warning(ref, message, d, ...other) {
return this.new_system_datom('warning', d, {ref, message}, ...other);
}
new_xemitter(...P) {
return new (require('./xemitter')).Xemitter(...P);
}
select(d, selector) {
var g, k, match, ref1, ref2, ref3, ref4, stamped_values, v;
if (selector == null) {
select(d, ...selectors) {
var i, len, ref, selector;
if (!(selectors.length > 0)) {
throw new Error("µ86606 expected a selector, got none");

@@ -270,44 +191,13 @@ }

}
//.......................................................................................................
if ((match = (ref1 = selector.match(p2)) != null ? ref1 : selector.match(p1)) == null) {
throw new Error(`µ37799 illegal selector ${rpr(selector)}`);
if ((ref = d.$stamped) != null ? ref : false) {
return false;
}
g = {};
ref2 = match.groups;
for (k in ref2) {
v = ref2[k];
if (v !== '') {
g[k] = v;
//.......................................................................................................
for (i = 0, len = selectors.length; i < len; i++) {
selector = selectors[i];
if ((this._get_matcher(selector))(d.$key)) {
return true;
}
}
if ((g.attribute != null) && (g.attribute !== 'stamped')) {
throw new Error(`µ77764 unknown attribute name ${rpr(g.attribute)}`);
}
switch (g.value) {
case void 0:
stamped_values = [false];
break;
case '*':
stamped_values = [true, false];
break;
case 'true':
stamped_values = [true];
break;
case 'false':
stamped_values = [false];
break;
default:
throw new Error(`µ33366 illegal attribute or value in selector ${rpr(selector)}`);
}
if (ref3 = (ref4 = d.$stamped) != null ? ref4 : false, indexOf.call(stamped_values, ref3) < 0) {
//.......................................................................................................
return false;
}
if (g.key != null) {
return d.$key === g.skey;
}
if (!d.$key.startsWith(g.sigil)) {
return false;
}
return true;
return false;
}

@@ -314,0 +204,0 @@

(function() {
'use strict';
var GUY, Intertype, base_types, debug, echo, get_base_types, get_xemitter_types, inspect, log, misfit, rpr, xemitter_types;
var GUY, Intertype, base_types, debug, echo, get_base_types, inspect, log, misfit, rpr;

@@ -25,4 +25,2 @@ //###########################################################################################################

xemitter_types = null;
misfit = Symbol('misfit');

@@ -53,16 +51,6 @@

//.........................................................................................................
/* TAINT ??? to be removed ??? */ declare.datom_sigil(function(x) {
return x === '^' || x === '<' || x === '>' || x === '~' || x === '[' || x === ']';
/* TAINT ??? to be removed ??? */ declare.datom_key(function(x) {
return (this.isa.text(x)) && (x.length > 0);
});
//.........................................................................................................
declare.datom_key(function(x) {
if (!this.isa.text(x)) {
return false;
}
if (!((Array.from(x)).length >= 2)) {
return false;
}
return this.isa.datom_sigil(x[0]);
});
//.........................................................................................................
declare.datom_name('nonempty.text');

@@ -104,19 +92,4 @@ //.........................................................................................................

//-----------------------------------------------------------------------------------------------------------
get_xemitter_types = function() {
var declare;
if (xemitter_types != null) {
return xemitter_types;
}
//.........................................................................................................
xemitter_types = new Intertype(get_base_types());
({declare} = xemitter_types);
//.........................................................................................................
declare.callable('function');
//.........................................................................................................
return xemitter_types;
};
//===========================================================================================================
module.exports = {misfit, get_base_types, get_xemitter_types};
module.exports = {misfit, get_base_types};

@@ -123,0 +96,0 @@ }).call(this);

{
"name": "datom",
"version": "11.0.0",
"version": "12.0.0",
"description": "standardized immutable objects in the spirit of datomic, especially suited for use in data pipelines",

@@ -26,4 +26,4 @@ "main": "lib/main.js",

"dependencies": {
"guy": "^12.7.0",
"intertype": "0.111.0",
"guy": "^13.5.0",
"intertype": "0.114.0",
"letsfreezethat": "^3.1.0"

@@ -30,0 +30,0 @@ },

@@ -24,8 +24,2 @@

- [`select = ( d, selector ) ->`](#select---d-selector---)
- [The XEmitter (XE) Sub-Module](#the-xemitter-xe-sub-module)
- [XE Sending API](#xe-sending-api)
- [XE Receiving API](#xe-receiving-api)
- [Sample](#sample)
- [Managing Scope](#managing-scope)
- [Cup Of Datom](#cup-of-datom)
- [Benchmarks](#benchmarks)

@@ -68,3 +62,3 @@ - [To Do](#to-do)

Or, mode idiomatically:
Or, more idiomatically:

@@ -329,173 +323,2 @@ ```coffee

## The XEmitter (XE) Sub-Module
### XE Sending API
* **`XE.emit = ( key, d ) ->`** emit (a.k.a. 'publish', 'send to whom it may concern') an event. To
be called either as `XE.emit '^mykey', 'myvalue'` or as `XE.emit PD.new_event '^mykey', 'myvalue'` (in
which latter case the datom's key will become the channel key). When called with await as in
`return_values = await XE.emit '^foo', ...`, `return_values` will be a list with all values returned by
all listeners that got called for this event.
* **`XE.delegate = ( key, d ) ->`** like `XE.emit()` but will pick out and unwrap the event value
from the event contractor (see below). If no event contractor was listening, an error will be raised.
### XE Receiving API
* **`XE.listen_to_all = ( listener ) ->`** Register a listener for all events.
* **`XE.listen_to_unheard = ( listener ) ->`** Register a listener for all events that do not have a
listener or a contractor.
* **`XE.listen_to = ( key, listener ) ->`** Register a listener for events that match `key`. No
pattern matching is implemented atm, so you can only listen to all keys or a single key.
* **`XE.contract = ( key, listener ) ->`** Register a contractor (a.k.a. 'result producer') for
events that match `key`.
<!-- The above methods—`XE.listen_to_all()`, `XE.listen_to()` and `XE.contract()`—will return an `unsubscribe()`
function that, when called once, will unsubscribe the event listener from the event.
-->
### Sample
```coffee
PD = require 'pipedreams'
defer = setImmediate
XE = PD.XE.new_scope()
#-----------------------------------------------------------------------------------------------------------
### Register a 'contractor' (a.k.a. 'result producer') for `^plus-async` events; observe that asynchronous
contractors should return a promise: ###
XE.contract '^plus-async', ( d ) =>
return new Promise ( resolve, reject ) =>
defer => resolve d.value.a + d.value.b
############################################################################################################
do =>
info 'µ28823-5', await XE.emit PD.new_event '^plus-async', { a: 42, b: 108, }
# in case other listeners were registered that returned values like `'listener #1'` and so on, the
# returned list of values might look like:
# -> [ 'listener #4', { key: '~xemitter-preferred', value: 150 }, 'listener #1', 'listener #2' ]
### When using `delegate()` instead of `emit()`, the preferred value (a.k.a. '*the* event result')
will be picked out of the list and unwrapped for you: ###
info 'µ28823-6', await XE.delegate PD.new_event '^plus-async', { a: 42, b: 108, }
# -> 150
```
For a demo with more coverage, have a look at
[experiments/demo-xemitter.coffee](https://github.com/loveencounterflow/pipedreams/blob/master/blob/master/src/experiments/demo-xemitter.coffee).
### Managing Scope
Typically, you'll start using XEmitter with `XE = PD.XE.new_scope()`; this creates a new 'scope' for events.
Only methods that emit and listen to the same scope can exchange messages. When used within an application,
you will want to publish that scope to all participating modules; one way to do so is to write a dedicated
module with a single line in it, `module.exports = ( require 'pipedreams' ).XE.new_scope()`.
# Cup Of Datom
Class `Cupofdatom` is a derivative of [`Cupofjoe`](https://github.com/loveencounterflow/cupofjoe) that is
geared towards easy declarative generation of nested sequences of datoms with a
[teacup](https://github.com/goodeggs/teacup)-like syntax:
```coffee
c = new DATOM.Cupofdatom()
c.cram 'helo', 'world'
c.cram 'foo', ->
c.cram 'bold', ->
c.cram null, 'content'
ds = c.expand()
# `ds` is now a list of datoms:
[
{ $key: '<helo' },
{ $key: '^text', text: 'world' },
{ $key: '>helo' },
{ $key: '<foo' },
{ $key: '<bold' },
{ $key: '^text', text: 'content' },
{ $key: '>bold' },
{ $key: '>foo' } ]
```
* First argument to `cram()` becomes key of datom
* therefore, must be a valid datom name
* sigil will be `^` if called with no further arguments
* or else two datoms with sigils `<` and `>` will be generated that surround their contents
* text arguments will be turned into `^text` datoms
* as with `Cupofjoe`, functions will be called, may either call `cram()` method or return value
* return values will *not* be further analyzed but be kept as-is in the list returned by `expand()`
* also possible to provide (in non-initial positions) objects whose members will become attributes of the
respective datom:
```coffee
c = new DATOM.Cupofdatom { absorb: true, } # default value; Note: turn attributes off with { absorb: false, }
c.cram 'greeting', 'helo', 'world'
c.cram 'greeting', '早安', { lang: 'zh_CN', }
c.cram 'greeting', { lang: 'zh_CN', 问候: '早安', time_of_day: 'morning', }
c.cram 'text', { lang: 'hi', text: 'नमस्ते', }
c.cram 'greeting', ->
c.cram 'language', { $value: 'Japanese', }
c.cram 'time_of_day', { $value: 'morning', }
c.cram null, 'お早うございます'
```
gives
```
{ $key: '<greeting' }
{ $key: '^text', text: 'helo', }
{ $key: '^text', text: 'world', }
{ $key: '>greeting' }
{ $key: '<greeting', lang: 'zh_CN', }
{ $key: '^text', text: '早安', }
{ $key: '>greeting' }
{ $key: '^greeting', lang: 'zh_CN', '问候': '早安', time_of_day: 'morning', }
{ $key: '^text', text: 'नमस्ते', lang: 'hi', }
{ $key: '<greeting' }
{ $key: '^language', $value: 'Japanese', }
{ $key: '^time_of_day', $value: 'morning', }
{ $key: '^text', text: 'お早うございます', }
{ $key: '>greeting' }
```
Call patterns:
* first argument is always:
* the **basic name** (the `$key` of the datom minus the sigil) of the datom,
* or else the **comprehensive name**, where implemented (for example in InterText `CupOfHtml`, this means
one can give `div#c59.draggable.hilite` as first argument to produce elements with a tag name (`div`),
an ID (`c59`), and HTML `class` attribute (`draggable hilite`) in one go
* or else **`null`** to indicate absence of a specific name
* when a name has been given
* and there are content arguments, then a pair of `{ $key: '<name', }`, `{ $key: '>name', }` datoms
will be produced, with the content arguments coming in between
* in case no content has been given, a single `{ $key: '^name', }` datom will be produced
* as for arguments in non-initial positions:
* objects will be merged with `Object.assign()` and passed on to `DATOM.new_datom()`, so `cram 'foo', {
id: 'c221', frob: true, x: 1, }, ... { x: 2, }` will produce `{ $key: '^foo', id: 'c221', frob: true, x:
2, }`.
* In case a key/value pair attributes argument conflicts with one set by an comprehensive name (as in
`cram 'foo#IDA', { id: 'IDB', }`), the one in the attributes argument wins (as it would in a similar
situation when using `Object.assign()`)
* functions will be called without arguments
* if a function itself calls `cram()` from the same instance, its return value will be discarded;
* in case it does not call `cram()`, its return value will be discarded if it is `null` or `undefined`,
and otherwise become a content argument *without being processed*, so contained functions will not be
called and text values will not be wrapped in `{ $key: '^text', }` datoms
* texts will be wrapped in `{ $key: '^text', 'text': ..., }` datoms
* other values will be wrapped in `{ $key: '^value', '$value': ..., }` datoms, e.g. `cram null, 42, 'some
text', true` will emit `{ $key: '^value', $value: 42, }, { $key: '^text', $text: 'some text', }, { $key:
'^value', $value: true, }`
```coffee
cram name
cram name, content1, content2, ...
cram name, content1, ( -> function ), ...
cram name, content1, ( -> cram ... ), ...
cram name, { key: value, }, content1, ( -> cram ... ), ...
```
# Benchmarks

@@ -570,4 +393,6 @@

and cloning (`strcuturedClone()`, `Object.assign()`, `GUY.props.nonull_assign()`)
* [ ] re-implement (syntax or method for) selecting stamped datoms
* [ ] implement wildcards for `select()`; cache selectors to avoid re-interpretation of recurrent patterns

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc