@fireflysemantics/slice 17.0.5 → 17.0.7

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.
Files changed (2) hide show
  1. package/README.md +319 -19
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -6,6 +6,12 @@ Lightweight Javascript Reactive State Management for Angular Applications.
6
6
 
7
7
  If you like the [@fireflysemantics/slice API](https://fireflysemantics.github.io/slice/doc/) please star our [Github Repository](https://github.com/fireflysemantics/slice).
8
8
 
9
+ - [Install](#install)
10
+ - [Object Store Core Use Cases](#object-store-core-use-cases)
11
+ - [Entity Store Core Use Cases](#entity-store-core-use-cases)
12
+ - [Features](#features)
13
+ - [Documentatino and Media](#firefly-semantics-slice-development-center-media-and-documentation)
14
+
9
15
  # Install
10
16
 
11
17
 
@@ -28,6 +34,8 @@ npm i @fireflysemantics/slice@lastest nanoid
28
34
 
29
35
  # Usage
30
36
 
37
+ The project [typedoc](https://fireflysemantics.github.io/slice/typedoc/), in addition to providing more detailed API insight, syntax highlights all the examples provided here, thus you may want to check it out for a richer reading experience.
38
+
31
39
  ## Object Store Core Use Cases
32
40
 
33
41
  [Here is a link to the Stackblitz Demo](https://stackblitz.com/edit/typescript-9snt67?file=index.ts)
@@ -129,7 +137,316 @@ console.log(`The count is ${OS.count()}`);
129
137
  console.log(`The snapshot is ${OS.snapshot(OS.S.K1)}`);
130
138
  ```
131
139
 
140
+ ## Entity Store Core Use Cases
141
+
142
+ [Here is a link to the Stackblitz demo](https://stackblitz.com/edit/typescript-akqgqg?file=index.ts) containing the below demo code. You may also wish to check out the [test cases](https://github.com/fireflysemantics/slice/blob/master/projects/slice/src/lib/EStore.spec.ts) for the entity store which also detail usage scenarios.
143
+
144
+ ```
145
+ //============================================
146
+ // Demo Utilities
147
+ //============================================
148
+
149
+ export const enum TodoSliceEnum {
150
+ COMPLETE = 'Complete',
151
+ INCOMPLETE = 'Incomplete',
152
+ }
153
+
154
+ export class Todo {
155
+ constructor(
156
+ public complete: boolean,
157
+ public title: string,
158
+ public gid?: string,
159
+ public id?: string
160
+ ) {}
161
+ }
162
+
163
+ export const extraTodo: Todo = new Todo(false, 'Do me later.');
164
+
165
+ export let todos = [
166
+ new Todo(false, 'You complete me!'),
167
+ new Todo(true, 'You completed me!'),
168
+ ];
169
+
170
+ export function todosFactory(): Todo[] {
171
+ return [
172
+ new Todo(false, 'You complete me!'),
173
+ new Todo(true, 'You completed me!'),
174
+ ];
175
+ }
176
+
177
+ export function todosClone(): Todo[] {
178
+ return todos.map((obj) => ({ ...obj }));
179
+ }
180
+
181
+ //============================================
182
+ // API: constructor()
183
+ //
184
+ // Create a Todo Entity Store
185
+ //============================================
186
+ let store: EStore<Todo> = new EStore<Todo>(todosFactory());
187
+
188
+ //============================================
189
+ // API: post, put, delete
190
+ //
191
+ // Perform post (Create), put (Update), and delete opeartions
192
+ // on the store.
193
+ //============================================
194
+ const todoLater: Todo = new Todo(false, 'Do me later.');
195
+ todoLater.id = 'findMe';
196
+ store.post(todoLater);
197
+ const postedTodo = store.findOneByID('findMe');
198
+ postedTodo.title = 'Do me sooner';
199
+ store.put(postedTodo);
200
+ store.delete(postedTodo);
201
+
202
+ //============================================
203
+ // API: allSnapshot()
204
+ //
205
+ // Take a snapshot of all the entities
206
+ // in the store
207
+ //============================================
208
+ let snapshot: Todo[] = store.allSnapshot();
209
+
210
+ //============================================
211
+ // API: obs
212
+ //
213
+ // Create a subscription to the entities in
214
+ // the store.
215
+ //============================================
216
+ let todosSubscription: Subscription = store.obs.subscribe((todos: Todo[]) => {
217
+ console.log(`The store todos ${todos}`);
218
+ });
219
+
220
+ //============================================
221
+ // API: findOne()
222
+ //
223
+ // Find a Todo instance using the
224
+ // Global ID (guid) property.
225
+ //============================================
226
+ const globalID: string = '1';
227
+ let findThisTodo = new Todo(false, 'Find this Todo', globalID);
228
+
229
+ store.post(findThisTodo);
132
230
 
231
+ const todo = store.findOne(globalID);
232
+ console.log(todo);
233
+
234
+ //============================================
235
+ // API: findOneByID()
236
+ //
237
+ // Find a Todo instance using the
238
+ // ID (id) property.
239
+ //============================================
240
+ const ID: string = 'id';
241
+ let todoWithID = new Todo(false, 'Find this Todo by ID');
242
+ todoWithID.id = ID;
243
+
244
+ store.post(todoWithID);
245
+ const todoFoundByID = store.findOneByID(ID);
246
+
247
+ console.log(`The Todo instance found by id is ${todoFoundByID}`);
248
+
249
+ //============================================
250
+ // API: observeLoading()
251
+ //
252
+ // Subscribe to the store loading indicator
253
+ // and toggle it to see the values change.
254
+ //============================================
255
+ store.observeLoading().subscribe((loading) => {
256
+ console.log(`Is data loading: ${loading}`);
257
+ });
258
+ store.loading = true;
259
+ store.loading = false;
260
+
261
+ //============================================
262
+ // API: observeSearching()
263
+ //
264
+ // Subscribe to the store searching indicator
265
+ // and toggle it to see the values change.
266
+ //============================================
267
+ store.observeSearching().subscribe((searching) => {
268
+ console.log(`Is the store searching: ${searching}`);
269
+ });
270
+ store.searching = true;
271
+ store.searching = false;
272
+
273
+ //============================================
274
+ // API: addActive()
275
+ // Perform active state tracking. Initially the
276
+ // number of active entities will be zero.
277
+ //============================================
278
+ console.log(`The number of active Todo instances is ${store.active.size}`);
279
+ let todo1: Todo = new Todo(false, 'The first Todo!', GUID());
280
+ let todo2: Todo = new Todo(false, 'The first Todo!', GUID());
281
+ store.addActive(todo1);
282
+ console.log(`The number of active Todo instances is ${store.active.size}`);
283
+
284
+ console.log(
285
+ `The number of active Todo instances by the activeSnapshot is ${
286
+ store.activeSnapshot().length
287
+ }`
288
+ );
289
+
290
+ //============================================
291
+ // API: observeActive()
292
+ //
293
+ // Subscribing to the observeActive() observable
294
+ // provides the map of active Todo instances.
295
+ //============================================
296
+ store.observeActive().subscribe((active) => {
297
+ console.log(`The active Todo instances are: ${active}`);
298
+ });
299
+
300
+ //============================================
301
+ // API: deleteActive()
302
+ // Delete the active Todo instance.
303
+ // This will set the number of active
304
+ // Todo instances back to zero.
305
+ //============================================
306
+ store.deleteActive(todo1);
307
+ console.log(
308
+ `The number of active Todo instances by the activeSnapshot is ${
309
+ store.activeSnapshot().length
310
+ }`
311
+ );
312
+
313
+ //============================================
314
+ // API: count()
315
+ //
316
+ // Dyanically count the Number of Entries in the Store.
317
+ //============================================
318
+ let countSubscription = store.count().subscribe((c) => {
319
+ console.log(`The number of Todo entities stored is ${c}`);
320
+ });
321
+
322
+ //============================================
323
+ // API: toggle()
324
+ //
325
+ // When we post another todo using toggle
326
+ // instance the subscribed to count
327
+ // dynamically increases by 1.
328
+ // When we call toggle again,
329
+ // removing the instance the
330
+ // count decreases by 1.
331
+ //============================================
332
+ store.toggle(extraTodo);
333
+ store.toggle(extraTodo);
334
+
335
+ //============================================
336
+ // API: contains()
337
+ //
338
+ // When we post another todo using toggle
339
+ // the store now contains it.
340
+ //============================================
341
+ console.log(
342
+ `Does the store contain the extraTodo ${store.contains(extraTodo)}`
343
+ );
344
+ store.toggle(extraTodo);
345
+ console.log(
346
+ `Does the store contain the extraTodo ${store.contains(extraTodo)}`
347
+ );
348
+ store.toggle(extraTodo);
349
+ console.log(
350
+ `Does the store contain the extraTodo ${store.contains(extraTodo)}`
351
+ );
352
+
353
+ //============================================
354
+ // API: containsbyID()
355
+ //
356
+ // When we post another todo using toggle
357
+ // the store now contains it.
358
+ //
359
+ // Note the containsByID() can be called with
360
+ // both the id property or the entire instance.
361
+ //============================================
362
+ let todoByID = new Todo(false, 'This is not in the store', undefined, '1');
363
+ store.post(todoByID);
364
+ console.log(
365
+ `Does the store contain the todoByID ${store.containsById(todoByID.id)}`
366
+ );
367
+ console.log(
368
+ `Does the store contain the todoByID ${store.containsById(todoByID)}`
369
+ );
370
+ store.toggle(todoByID);
371
+ console.log(
372
+ `Does the store contain the todoByID ${store.containsById(todoByID.id)}`
373
+ );
374
+ console.log(
375
+ `Does the store contain the todoByID ${store.containsById(todoByID)}`
376
+ );
377
+
378
+ //============================================
379
+ // API: equalsByGUID and equalsByID
380
+ //
381
+ // Compare entities by ID and Global ID (guid).
382
+ // We will assign the ID and the global ID
383
+ // instead of allowing the global ID to be
384
+ // assigned by the store on post.
385
+ //============================================
386
+ const guid = GUID();
387
+ let todoOrNotTodo1 = new Todo(false, 'Apples to Apples', guid, '1');
388
+ let todoOrNotTodo2 = new Todo(false, 'Apples to Apples', guid, '1');
389
+
390
+ const equalByID: boolean = store.equalsByID(todoOrNotTodo1, todoOrNotTodo2);
391
+ console.log(`Are the todos equal by id: ${equalByID}`);
392
+ const equalByGUID: boolean = store.equalsByGUID(todoOrNotTodo1, todoOrNotTodo2);
393
+ console.log(`Are the todos equal by global id: ${equalByGUID}`);
394
+
395
+ //============================================
396
+ // API: addSlice
397
+ //
398
+ // Add a slice for complete todo entities.
399
+ //
400
+ // We create a new store to demo with a
401
+ // consistent count.
402
+ //
403
+ // When posting the extraTodo which is
404
+ // incomplete, we see that the incomplete
405
+ // count increments.
406
+ //============================================
407
+ store.destroy();
408
+ store = new EStore<Todo>(todosFactory());
409
+ store.addSlice((todo) => todo.complete, TodoSliceEnum.COMPLETE);
410
+ store.addSlice((todo) => !todo.complete, TodoSliceEnum.INCOMPLETE);
411
+ const completeSlice = store.getSlice(TodoSliceEnum.COMPLETE);
412
+ const incompleteSlice = store.getSlice(TodoSliceEnum.INCOMPLETE);
413
+ completeSlice.count().subscribe((c) => {
414
+ console.log(`The number of entries in the complete slice is ${c}`);
415
+ });
416
+ incompleteSlice.count().subscribe((c) => {
417
+ console.log(`The number of entries in the incomplete slice is ${c}`);
418
+ });
419
+ store.post(extraTodo);
420
+ const incompleteTodos: Todo[] = incompleteSlice.allSnapshot();
421
+ console.log(`The incomplete Todo entities are ${incompleteTodos}`);
422
+
423
+ //============================================
424
+ // API: isEmpty()
425
+ //
426
+ // Check whether the store is empty.
427
+ //============================================
428
+ store.isEmpty().subscribe((empty) => {
429
+ console.log(`Is the store empty? ${empty}`);
430
+ });
431
+ ```
432
+
433
+ ## Features
434
+
435
+ - Live Stackblitz demoes
436
+ - [Typedoc with inlined examples](https://fireflysemantics.github.io/slice/doc/)
437
+ - [Well documented test cases run with Jest - Each file has a corresponding `.spec` file](https://github.com/fireflysemantics/slice/tree/master/src)
438
+ - Stream both Entity and Object Stores for UI Updates via RxJS
439
+ - Define entities using Typescript classes, interfaces, or types
440
+ - [Active state tracking](https://medium.com/@ole.ersoy/monitoring-the-currently-active-entity-with-slice-ff7c9b7826e8)
441
+ - [Supports for Optimistic User Interfaces](https://medium.com/@ole.ersoy/optimistic-user-identity-management-with-slice-a2b66efe780c)
442
+ - RESTful API for performing CRUD operations that stream both full and delta updates
443
+ - Dynamic creation of both object and entity stores
444
+ - Observable delta updates for Entities
445
+ - Real time application of Slice `Predicate<E>` filtering that is `Observable`
446
+ - `Predicate` based snapshots of entities
447
+ - Observable `count` of entities in the entity store. The `count` feature can also be `Predicate` filtered.
448
+ - Configurable global id (Client side id - `gid`) and server id (`id`) id property names for entities.
449
+ - The stream of entities can be sorted via an optional boolean expression passed to `observe`.
133
450
 
134
451
  # Firefly Semantics Slice Development Center Media and Documentation
135
452
 
@@ -193,7 +510,7 @@ console.log(`The snapshot is ${OS.snapshot(OS.S.K1)}`);
193
510
 
194
511
  # API Documentation
195
512
 
196
- See [Typedoc API Documentation](https://fireflysemantics.github.io/slice/doc/)
513
+ See [Typedoc API Documentation](https://fireflysemantics.github.io/slice/typedoc/)
197
514
 
198
515
  The documentation for the API includes simple examples of how to apply the API to a use case.
199
516
 
@@ -221,26 +538,9 @@ Run `npm run c` to build the project. The build artifacts will be stored in the
221
538
 
222
539
  ## Running unit tests
223
540
 
224
- Run `ng test` to execute the unit tests via [Jest](https://jestjs.io/).
225
-
541
+ Run `npm run test` to execute the unit tests via [Jest](https://jestjs.io/).
226
542
 
227
- ## Features
228
543
 
229
- - Live Stackblitz demoes
230
- - [Typedoc with inlined examples](https://fireflysemantics.github.io/slice/doc/)
231
- - [Well documented test cases run with Jest - Each file has a corresponding `.spec` file](https://github.com/fireflysemantics/slice/tree/master/src)
232
- - Stream both Entity and Object Stores for UI Updates via RxJS
233
- - Define entities using Typescript classes, interfaces, or types
234
- - [Active state tracking](https://medium.com/@ole.ersoy/monitoring-the-currently-active-entity-with-slice-ff7c9b7826e8)
235
- - [Supports for Optimistic User Interfaces](https://medium.com/@ole.ersoy/optimistic-user-identity-management-with-slice-a2b66efe780c)
236
- - RESTful API for performing CRUD operations that stream both full and delta updates
237
- - Dynamic creation of both object and entity stores
238
- - Observable delta updates for Entities
239
- - Real time application of Slice `Predicate<E>` filtering that is `Observable`
240
- - `Predicate` based snapshots of entities
241
- - Observable `count` of entities in the entity store. The `count` feature can also be `Predicate` filtered.
242
- - Configurable global id (Client side id - `gid`) and server id (`id`) id property names for entities.
243
- - The stream of entities can be sorted via an optional boolean expression passed to `observe`.
244
544
 
245
545
  ## Tests
246
546
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fireflysemantics/slice",
3
- "version": "17.0.5",
3
+ "version": "17.0.7",
4
4
  "peerDependencies": {
5
5
  "nanoid": "^5.0.4",
6
6
  "@types/nanoid": "*",