@compilacion/colleciones-clientos 2.0.2 → 2.0.4

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
@@ -38,16 +38,64 @@ const tracker = new CollecionesTracker([emitter], 'myTracker', 'myApp');
38
38
 
39
39
  You can construct events declaratively using a natural language-like DSL:
40
40
 
41
+ Most simplistic use case
41
42
  ```js
42
43
  import collecionesDsl from './src/collecionesDsl.js';
43
44
 
44
45
  collecionesDsl
45
- .the('red')
46
- ._('button')
47
- .has.been('clicked')
46
+ .the('button') // Entity
47
+ .has.been('clicked') // Verb
48
+ .then.track.with(emitter); // Send
49
+ ```
50
+
51
+ Adding adjectives (states etc) onto the entity
52
+ ```js
53
+ import collecionesDsl from './src/collecionesDsl.js';
54
+
55
+ collecionesDsl
56
+ .the('red') // So now this is the adjective
57
+ ._('button') // and this becomes the entity
58
+ .has.been('clicked') // still the verb
48
59
  .then.track.with(emitter);
49
60
  ```
50
61
 
62
+ Full syntax:
63
+ ```js
64
+ import collecionesDsl from './src/collecionesDsl.js';
65
+
66
+ collecionesDsl
67
+ the('dark') // adjective 1
68
+ .and('green') // adjective 2
69
+ ._('button') // the entity
70
+ .identified.by('id') // the identifier-name for the entity
71
+ .as('button12') // the identifier-value for the entity
72
+ .and.by('externalReference') // yet another reference
73
+ .as ('ext-123') // and it's idnetifier value
74
+ .has.been('clicked') // the verb
75
+ .by('user') // the actor (a user or a system or ..)
76
+ .identified.by('usrId') // an id for a user
77
+ .as('abc-123') // the id value
78
+ .and('email') // another id for the user
79
+ .as('jef@email.com') // the id value
80
+ .with('sourcePage').set.to('homepage') // context
81
+ .and('ctaLabel').set.to('register-now') // context
82
+ .including.a('property').collection()
83
+ .with
84
+ .item.identified.by('propertyId').as('1')
85
+ .and.by('externalId').as('12')
86
+ .and.item.identified.by('propertyId').as('2')
87
+ .and.by('externalId').as('13')
88
+ .and.a('suggest').collection()
89
+ .with
90
+ .item.identified.by('suggestionId').as('1')
91
+ .and.item.identified.by('suggestionId').as('2')
92
+ .referring.to('property') // to what entities this event refers
93
+ .identified.by('id') // optional
94
+ .as('123') // required when preceding with 'identified'
95
+ .conform.to('UserInteractionEvent') // if applicable which schema it should follow
96
+ .then.track.with(emitter);
97
+ ```
98
+
51
99
  📘 See [docs/dsl.md](./docs/dsl.md) for full DSL documentation.
52
100
 
53
101
  ### 4. Manually Create Events (Optional)
@@ -43,13 +43,34 @@
43
43
  };
44
44
 
45
45
  /**
46
- * Base class representing a structured event with timestamp, identifiers, and data fields.
47
- * This class is used to model events in a semantic and structured format for tracking purposes.
46
+ * CollecionesEvent
47
+ * -----------------
48
+ * Base class representing a semantically structured event object.
49
+ * Each event models a specific interaction with an entity, optionally performed by an actor,
50
+ * and may reference related entities or include contextual metadata.
51
+ *
52
+ * Key features:
53
+ * - Captures structured semantics: entity, action, actor, context, references
54
+ * - Supports multiple identifiers for both the main entity and the actor
55
+ * - Allows origin tagging for cross-context or cross-application references
56
+ * - Supports referencing collections of entities or grouped data
57
+ * - Includes timestamps and tracker/app metadata for auditability
58
+ * - Fully serializable and deserializable via toJSON/fromJSON
48
59
  */
49
60
  class CollecionesEvent {
50
61
 
51
62
  /**
52
- * Constructs a new event with default metadata and timestamps.
63
+ * Constructs a new CollecionesEvent with default structure and timestamps.
64
+ * Initializes empty containers for semantic attributes such as:
65
+ * - entity: the subject of the event
66
+ * - adjectives: descriptors of the entity
67
+ * - identifiers: identifiers of the entity
68
+ * - action: what happened to the entity
69
+ * - actor: who or what triggered the event (with identifiers in actorIdentifiers)
70
+ * - context: environmental data related to the event
71
+ * - references: external entities involved, optionally scoped by origin
72
+ * - collections: groups of related entities
73
+ * - meta: tracking metadata and timestamps
53
74
  */
54
75
  constructor() {
55
76
  // initialize event properties
@@ -61,6 +82,7 @@
61
82
  this.actorIdentifiers = {};
62
83
  this.context = {};
63
84
  this.references = {};
85
+ this.collections = {};
64
86
  // set default values
65
87
  this.meta = {
66
88
  eventFormat: 'CollecionesEvent',
@@ -164,6 +186,7 @@
164
186
 
165
187
  /**
166
188
  * Adds or updates an identifier for the primary entity.
189
+ * Identifiers allow multiple keys to uniquely identify the entity.
167
190
  * @param {string} name - The identifier key.
168
191
  * @param {*} identifier - The identifier value.
169
192
  */
@@ -176,7 +199,7 @@
176
199
 
177
200
  /**
178
201
  * Defines the name of the actor (who or what performed the action).
179
- * @param {string} name - Actor name (e.g., 'user').
202
+ * @param {string} name - Actor name (e.g., 'user', 'system').
180
203
  */
181
204
  setActor = function(name) {
182
205
  if (typeof name !== 'string') {
@@ -187,7 +210,8 @@
187
210
 
188
211
  /**
189
212
  * Adds or updates an identifier for the actor.
190
- * @param {string} name - Identifier name.
213
+ * Supports multiple identifiers to uniquely identify the actor.
214
+ * @param {string} name - Identifier key.
191
215
  * @param {*} identifier - Identifier value.
192
216
  */
193
217
  setActorIdentifier = function(name, identifier) {
@@ -199,6 +223,7 @@
199
223
 
200
224
  /**
201
225
  * Adds contextual information to the event.
226
+ * Context can include any additional environmental or situational data.
202
227
  * @param {string} context - The key of the context field.
203
228
  * @param {*} value - The value of the context field.
204
229
  */
@@ -209,39 +234,128 @@
209
234
  this.context[context] = value;
210
235
  }
211
236
 
237
+ /**
238
+ * Alias for `setReference` for compatibility.
239
+ * Declares an external entity referenced by this event.
240
+ * @param {string} entity - The referenced entity name.
241
+ * @param {string|null} origin - The origin application or context (optional).
242
+ */
243
+ setRefence = function(entity, origin=null) {
244
+ return this.setReference(entity, origin);
245
+ }
246
+
212
247
  /**
213
248
  * Declares an entity referenced by this event.
249
+ * References may include multiple identifiers and an optional origin to scope the reference.
214
250
  * @param {string} entity - The referenced entity name.
251
+ * @param {string|null} origin - The origin application or context (optional).
215
252
  */
216
- setRefence = function(entity) {
253
+ setReference = function(entity, origin=null) {
217
254
  if (typeof entity !== 'string') {
218
255
  throw new Error('Referenced entity must be a string');
219
256
  }
220
257
  if(this.references[entity] === undefined) {
221
- this.references[entity] = {identifiers: {}};
258
+ this.references[entity] = {
259
+ identifiers: {},
260
+ origin
261
+ };
222
262
  }
223
263
  }
224
264
 
265
+ /**
266
+ * Adds or updates an identifier for a referenced entity.
267
+ * Ensures the reference is declared and sets the identifier under that reference.
268
+ * @param {string} entity - The referenced entity name.
269
+ * @param {string} name - The identifier key.
270
+ * @param {*} identifier - The identifier value.
271
+ * @param {string|null} origin - Optional origin context.
272
+ */
273
+ setRefenceIdentifier = function(entity, name, identifier, origin=null) {
274
+ return this.setReferenceIdentifier(entity, name, identifier, origin);
275
+ }
276
+
225
277
  /**
226
278
  * Adds or updates an identifier for a referenced entity.
227
279
  * @param {string} entity - The referenced entity name.
228
280
  * @param {string} name - The identifier key.
229
281
  * @param {*} identifier - The identifier value.
282
+ * @param {string|null} origin - Optional origin context.
230
283
  */
231
- setRefenceIdentifier = function(entity, name, identifier) {
284
+ setReferenceIdentifier = function(entity, name, identifier, origin=null) {
232
285
  if (typeof entity !== 'string') {
233
286
  throw new Error('Referenced entity name must be a string');
234
287
  }
235
288
  if (typeof name !== 'string') {
236
289
  throw new Error('Actor Identifier name must be a string');
237
290
  }
238
- this.setRefence(entity);
291
+ this.setRefence(entity, origin);
239
292
  this.references[entity].identifiers[name] = identifier;
240
293
  }
241
294
 
242
295
  /**
243
- * Serializes the event to a plain object suitable for JSON.stringify().
244
- * @returns {object}
296
+ * Declares a collection of related entities for this event.
297
+ * Collections group multiple related items and may include identifiers and origin metadata.
298
+ * @param {string} entity - The collection name.
299
+ * @param {string|null} origin - Optional origin identifier (e.g. system name).
300
+ */
301
+ setCollection = function(entity, origin=null) {
302
+ if(this.collections[entity] == undefined) {
303
+ this.collections[entity] = {
304
+ items: [],
305
+ identifiers: {},
306
+ origin
307
+ };
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Adds a new item to a collection and returns its index key.
313
+ * Items represent individual elements within the collection.
314
+ * @param {string} entity - The name of the collection.
315
+ * @returns {number} Index of the newly added item in the collection.
316
+ */
317
+ setCollectionItem = function(entity) {
318
+ this.setCollection(entity);
319
+ this.collections[entity].items.push({});
320
+ let itemKey = this.collections[entity].items.length - 1;
321
+ return itemKey;
322
+ }
323
+
324
+ /**
325
+ * Assigns a reference (identifier) to a specific item in a collection.
326
+ * Useful for tagging individual collection elements with identifiers.
327
+ * @param {string} entity - Collection name.
328
+ * @param {number} itemKey - The index of the item in the collection.
329
+ * @param {string} name - The identifier key.
330
+ * @param {*} identifier - The identifier value.
331
+ * @throws {Error} If the item does not exist at the given index.
332
+ */
333
+ setCollectionItemReference = function(entity, itemKey, name, identifier) {
334
+ this.setCollection(entity);
335
+ if(typeof this.collections[entity].items[itemKey] !== 'object') {
336
+ throw new Error('bad bad man, the collection key does not exists');
337
+ }
338
+ this.collections[entity].items[itemKey][name] = identifier;
339
+ }
340
+
341
+ /**
342
+ * Sets a static identifier that applies to the entire collection.
343
+ * These identifiers describe the collection as a whole.
344
+ * @param {string} entity - Collection name.
345
+ * @param {string} name - Identifier key.
346
+ * @param {*} identifier - Identifier value.
347
+ */
348
+ setCollectionIdentifier = function(entity, name, identifier) {
349
+ if(this.collections[entity] == undefined) {
350
+ this.collections[entity] = {};
351
+ }
352
+ this.collections[entity].identifiers[name] = identifier;
353
+ }
354
+
355
+ /**
356
+ * Serializes the event instance to a plain object suitable for transport or storage.
357
+ * The output includes all semantic fields and metadata.
358
+ * @returns {object} A plain JavaScript object representing the event.
245
359
  */
246
360
  toJSON() {
247
361
  return {
@@ -255,14 +369,17 @@
255
369
  actorIds: this.actorIds,
256
370
  context: this.context,
257
371
  references: this.references,
258
- meta: this.meta
372
+ meta: this.meta,
373
+ collections: this.collections
259
374
  };
260
375
  }
261
376
 
262
377
  /**
263
- * Recreates an instance of CollecionesEvent from a plain object.
264
- * @param {object} obj
265
- * @returns {CollecionesEvent}
378
+ * Recreates a CollecionesEvent instance from a plain object.
379
+ * Used when deserializing events from storage or network transport.
380
+ * @param {object} obj - The input object containing event data.
381
+ * @returns {CollecionesEvent} A rehydrated event instance.
382
+ * @throws {Error} If the class type is not 'CollecionesEvent'.
266
383
  */
267
384
  static fromJSON(obj) {
268
385
  if (!obj || obj.class !== 'CollecionesEvent') {
@@ -279,6 +396,7 @@
279
396
  instance.context = obj.context || {};
280
397
  instance.references = obj.references || {};
281
398
  instance.meta = obj.meta || {};
399
+ instance.collections = obj.collections || {};
282
400
  return instance;
283
401
  }
284
402
 
@@ -544,9 +662,9 @@
544
662
  let addContext = () => {}; // .with(...).set.to(...)
545
663
  let addReference = () => {}; // .referring.to(...)
546
664
  let getAddReference = () => {}; // .identified.by().as() inside .referring
547
- let addReferenceIdentifier = () => {}; // .and(...) after reference
548
665
  let conformingTo = () => {}; // .conform.to('SchemaName')
549
666
  let track = () => {}; // .then.track.with(emitter)
667
+ let addCollection = () => {};
550
668
 
551
669
  // Adjective chaining: .and(...)._('entity')
552
670
  setEntityAfterAnd = (entity) => {
@@ -602,6 +720,9 @@
602
720
  with: addContext,
603
721
  conform: {to: conformingTo},
604
722
  then: {track: {with: track}},
723
+ including: {
724
+ a: addCollection,
725
+ },
605
726
  helpers
606
727
  }
607
728
  };
@@ -614,6 +735,9 @@
614
735
  by: setActorIdentifier
615
736
  },
616
737
  with: addContext,
738
+ including: {
739
+ a: addCollection,
740
+ },
617
741
  helpers
618
742
  }
619
743
  };
@@ -628,6 +752,9 @@
628
752
  and: setActorIdentifier,
629
753
  with: addContext,
630
754
  referring: { to: addReference },
755
+ including: {
756
+ a: addCollection,
757
+ },
631
758
  }
632
759
  },
633
760
  helpers
@@ -645,6 +772,9 @@
645
772
  helpers,
646
773
  and: addContext,
647
774
  referring: { to: addReference },
775
+ including: {
776
+ a: addCollection,
777
+ },
648
778
  }
649
779
  }
650
780
  }
@@ -660,6 +790,9 @@
660
790
  },
661
791
  conform: {to: conformingTo},
662
792
  then: {track: {with: track}},
793
+ including: {
794
+ a: addCollection,
795
+ },
663
796
  helpers
664
797
  }
665
798
  };
@@ -672,9 +805,12 @@
672
805
  eventInstance.setRefenceIdentifier(entity, name, value);
673
806
  return {
674
807
  helpers,
675
- and: addReferenceIdentifier,
808
+ and: {by: getAddReference(entity) },
676
809
  conform: {to: conformingTo},
677
810
  then: {track: {with: track}},
811
+ including: {
812
+ a: addCollection,
813
+ },
678
814
  }
679
815
  },
680
816
  helpers,
@@ -691,6 +827,61 @@
691
827
  }
692
828
  };
693
829
 
830
+ addCollection = (entity) => {
831
+ const collection = () => {
832
+ eventInstance.setCollection(entity);
833
+
834
+ const addItem = (referenceName) => {
835
+ const itemKey = eventInstance.setCollectionItem(entity);
836
+ const addIdentifier = (referenceNameNewIdentifier) => {
837
+ referenceName = referenceNameNewIdentifier;
838
+ return {
839
+ as: addItemReferenceValue,
840
+ }
841
+ };
842
+ const addItemReferenceValue = (value) => {
843
+ eventInstance.setCollectionItemReference(entity, itemKey, referenceName, value);
844
+ return {
845
+ and: {
846
+ helpers,
847
+ by: addIdentifier,
848
+ item: {
849
+ identified: {
850
+ by: addItem
851
+ }
852
+ },
853
+ a: addCollection
854
+ },
855
+ conform: {
856
+ to: conformingTo,
857
+ },
858
+ then: {track: {with: track}},
859
+ helpers
860
+ }
861
+ };
862
+ return {
863
+ as: addItemReferenceValue
864
+ }
865
+
866
+ };
867
+
868
+ return {
869
+ helpers,
870
+ with: {
871
+ item: {
872
+ identified: {
873
+ by: addItem
874
+ }
875
+ }
876
+ },
877
+ and: { a: addCollection }
878
+ }
879
+ };
880
+ return {
881
+ collection
882
+ }
883
+ };
884
+
694
885
  // Final dispatch: .then.track.with(tracker)
695
886
  track = (tracker) => {
696
887
  if(!(tracker instanceof CollecionesTracker)){