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