@fireflysemantics/slice 16.2.13 → 16.2.15
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 +116 -11
- package/esm2020/lib/OStore.mjs +145 -0
- package/fesm2015/fireflysemantics-slice.mjs +1506 -0
- package/fesm2015/fireflysemantics-slice.mjs.map +1 -0
- package/{fesm2022 → fesm2020}/fireflysemantics-slice.mjs +28 -16
- package/{fesm2022 → fesm2020}/fireflysemantics-slice.mjs.map +1 -1
- package/lib/OStore.d.ts +18 -12
- package/package.json +11 -5
- package/esm2022/lib/OStore.mjs +0 -133
- /package/{esm2022 → esm2020}/fireflysemantics-slice.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/AbstractStore.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/EStore.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/Slice.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/models/ActionTypes.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/models/Delta.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/models/Entity.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/models/Predicate.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/models/StoreConfig.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/models/constants.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/models/index.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/models/scrollPosition.mjs +0 -0
- /package/{esm2022 → esm2020}/lib/utilities.mjs +0 -0
- /package/{esm2022 → esm2020}/public-api.mjs +0 -0
package/README.md
CHANGED
@@ -1,27 +1,132 @@
|
|
1
|
+
[](https://travis-ci.org/fireflysemantics/slice)
|
2
|
+
|
3
|
+

|
4
|
+
|
1
5
|
# @fireflysemantics/slice
|
2
6
|
|
3
|
-
|
7
|
+
Lightweight Javascript Reactive State Management for Web Applications.
|
8
|
+
|
9
|
+
If you like the [@fireflysemantics/slice API](https://fireflysemantics.github.io/slice/doc/) please star our [Github Repository](https://github.com/fireflysemantics/slice).
|
10
|
+
|
11
|
+
# Install
|
12
|
+
|
13
|
+
Install Slice with peer dependencies:
|
14
|
+
|
15
|
+
```
|
16
|
+
npm i @fireflysemantics/slice tslib rxjs nanoid
|
17
|
+
```
|
18
|
+
|
19
|
+
# Firefly Semantics Slice Development Center Media and Documentation
|
20
|
+
|
21
|
+
## Concepts
|
22
|
+
|
23
|
+
- [What is Reactive State Management](https://developer.fireflysemantics.com/concepts/concepts--slice--what-is-reactive-state-management)
|
24
|
+
|
25
|
+
## Guides
|
26
|
+
|
27
|
+
- [An Introduction to the Firefly Semantics Slice Reactive Object Store](https://developer.fireflysemantics.com/guides/guides--introduction-to-the-firefly-semantics-slice-reactive-object-store)
|
28
|
+
- [Introduction to the Firefly Semantics Slice Reactive Entity Store ](https://developer.fireflysemantics.com/guides/guides--introduction-to-the-firefly-semantics-slice-reactive-entity-store)
|
29
|
+
- [Creating a Reactive Todo Application With the Firefly Semantics Slice State Manager](https://developer.fireflysemantics.com/guides/guides--slice--creating-a-reactive-todo-application-with-the-firefly-semantics-slice-state-manager)
|
30
|
+
- [Recreating the Ngrx Demo with Slice](https://developer.fireflysemantics.com/guides/guides--recreating-the-ngrx-demo-app-with-firefly-semantics-slice-state-manager)
|
31
|
+
- [Firefly Semantics Slice Entity Store Active API Guide](https://developer.fireflysemantics.com/guides/guides--slice--managing-active-entities-with-firefly-semantics-slice)
|
32
|
+
|
4
33
|
|
5
|
-
##
|
34
|
+
## Tasks
|
6
35
|
|
7
|
-
|
36
|
+
- [Creating a Minimal Slice Object Store](https://developer.fireflysemantics.com/examples/examples--slice--minimal-slice-object-store)
|
37
|
+
- [Creating a Minimal Angular Slice Object Store Angular State Service ](https://developer.fireflysemantics.com/examples/examples--slice--minial-angular-slice-object-store-state-service)
|
38
|
+
- [Changing the Firefly Semantics Slice EStore Default Configuration](https://developer.fireflysemantics.com/tasks/tasks--slice--changing-the-fireflysemantics-slice-estore-default-configuration)
|
39
|
+
- [Observing the Currently Active Entities with Slice](https://developer.fireflysemantics.com/tasks/tasks--slice--observing-currently-active-entities-with-slice)
|
40
|
+
- [Derived Reactive Observable State with Slice](https://developer.fireflysemantics.com/tasks/tasks--slice--derived-reactive-observable-state-with-slice)
|
41
|
+
- [Reactive Event Driven Actions with Firefly Semantics Slice](https://developer.fireflysemantics.com/tasks/tasks--slice--reactive-event-driven-actions-with-firefly-semantics-slice)
|
42
|
+
- [Unsubscribing From Firefly Semantics Slice Object Store Observables in Angular](https://developer.fireflysemantics.com/tasks/tasks--slice--unsubscribing-from-firefly-semantics-slice-object-store-observables-in-angular)
|
43
|
+
- [Creating Proxies to Slice Object Store Observables](https://developer.fireflysemantics.com/tasks/tasks--slice--creating-proxies-to-slice-object-store-observables)
|
44
|
+
- [Getting a Snapshot of a Slice Object Store Value](https://developer.fireflysemantics.com/tasks/tasks--slice--getting-a-snapshot-of-a-slice-object-store-value)
|
45
|
+
- [Accessing Slice Object Store Observables In Angular Templates](https://developer.fireflysemantics.com/tasks/tasks--slice--accessing-slice-object-store-observables-in-angular-templates)
|
46
|
+
- [Observing the Count of Items in a Firefly Semantics Slice Entity Store](https://developer.fireflysemantics.com/tasks/tasks--slice--observing-the-count-of-items-in-a-firefly-semantics-slice-entity-store)
|
47
|
+
- [Setting and Observing Firefly Semantics Slice Entity Store Queries](https://developer.fireflysemantics.com/tasks/tasks--slice--setting-and-observing-firefly-semantics-slice-entity-store-queries)
|
48
|
+
- [Taking a Count Snapshot of a Firefly Semantics Slice Entity Store](https://developer.fireflysemantics.com/tasks/tasks--slice--taking-a-count-snapshot-of-a-firefly-semantics-slice-entity-store)
|
49
|
+
- [Taking a Query Snapshot of a Firefly Semantics Slice Entity Store](https://developer.fireflysemantics.com/tasks/tasks--slice--taking-a-query-snapshot-of-a-firefly-semantics-slice-entity-store)
|
50
|
+
- [Adding Slices to an Firefly Semantics Slice Entity Store](https://developer.fireflysemantics.com/tasks/tasks--slice--adding-slices-to-the-firefly-semantics-entity-store)
|
51
|
+
- [Adding Search To the Firefly Semantics Slice Angular Todo Application](https://developer.fireflysemantics.com/tasks/tasks--slice--adding-search-to-the-firefly-semantics-slice-angular-todo-application)
|
52
|
+
- [Comparing Firefly Semantics Slice Entities](https://developer.fireflysemantics.com/tasks/tasks--slice--comparing-firefly-semantics-slice-entities)
|
53
|
+
- [Filtering Firefly Semantics Slice Object Store Observables by Property Value](https://developer.fireflysemantics.com/tasks/tasks--slice--filtering-firefly-semantics-slice-object-store-observables-by-property-value)
|
8
54
|
|
9
|
-
## Code scaffolding
|
10
55
|
|
11
|
-
|
56
|
+
## Youtube
|
57
|
+
|
58
|
+
- [What is Reactive State Management](https://youtu.be/kEta1LBVw0c)
|
59
|
+
- [An Introduction to the Firefly Semantics Slice Reactive Object Store](https://youtu.be/_3_mEKw3bM0)
|
60
|
+
- [Introduction to the Firefly Semantics Slice Reactive Entity Store ](https://youtu.be/Boj3-va-TKk)
|
61
|
+
- [Creating a Reactive Todo Application With the Firefly Semantics Slice State Manager](https://youtu.be/Y3AxSIiBdWg)
|
62
|
+
- [Recreating the Ngrx Demo with Slice](https://youtu.be/4t95RvJSY_8)
|
63
|
+
- [Setting and Observing the Firefly Semantics Slice Entity Store Query](https://youtu.be/_L5ya1CWaYU)
|
64
|
+
- [Observing the Count of Items in a Firefly Semantics Slice Entity Store](https://youtu.be/5kqr_XW2QuI)
|
65
|
+
- [Taking a Count Snapshot of a Firefly Semantics Slice Entity Store](https://youtu.be/n37sz4LPV08)
|
66
|
+
- [Taking a Query Snapshot of a Firefly Semantics Slice Entity Store](https://youtu.be/AFk5p0pNxSk)
|
67
|
+
- [Adding Slices to an Firefly Semantics Slice Entity Store](https://youtu.be/z2U6OTAsc4I)
|
68
|
+
- [Adding Search To the Firefly Semantics Slice Angular Todo Application](https://youtu.be/OkiBnU3Q6RU)
|
69
|
+
- [Converting the Angular Todo Application From Materialize to Angular Material](https://youtu.be/GPfF31hwxQk)
|
70
|
+
- [Firefly Semantics Slice Entity Store Active API Guide](https://youtu.be/fInpMcZ9Ry8)
|
71
|
+
- [Comparing Firefly Semantics Slice Entities](https://youtu.be/AYc3Pf9fSKg)
|
72
|
+
- [Derived Reactive Observable State with Slice](https://youtu.be/eDJkSgYhFIM)
|
73
|
+
|
74
|
+
## Examples
|
75
|
+
|
76
|
+
- [Minimal Slice Object Store](https://developer.fireflysemantics.com/examples/examples--slice--minimal-slice-object-store)
|
77
|
+
- [Minimal Angular Slice Object Store State Service](https://developer.fireflysemantics.com/examples/examples--slice--minial-angular-slice-object-store-state-service)
|
78
|
+
|
79
|
+
# API Documentation
|
80
|
+
|
81
|
+
See [Typedoc API Documentation](https://fireflysemantics.github.io/slice/doc/)
|
82
|
+
|
83
|
+
The documentation for the API includes simple examples of how to apply the API to a use case.
|
84
|
+
|
85
|
+
# Overview
|
86
|
+
|
87
|
+
Lightweight Reactive Server, Mobile, and Web Application State Management Built with `RxJS` and `Typescript`.
|
88
|
+
|
89
|
+
The API is designed to be as minimal as possible and should deliver the same features as other comparable frameworks with about 1/3 the lines of code.
|
90
|
+
|
91
|
+
It offers two types of reactive data stores:
|
92
|
+
- Entity stores (EStore<E>) for structured entity like data (Customer, Product, User, ...)
|
93
|
+
- Entity stores can be "Live filtered" by adding slices. For example separating Todo entities into complete and incomplete compartments. Slices are also obserable.
|
94
|
+
- Object store (Key value store) for unstructured data
|
95
|
+
|
96
|
+
Even though Angular is used for prototype applications, it should work well for:
|
97
|
+
- Single page applications
|
98
|
+
- Progressive web applications
|
99
|
+
- React applications
|
100
|
+
- Node applications / Pure Javascript Applications
|
101
|
+
- Mobile Applications
|
12
102
|
|
13
103
|
## Build
|
14
104
|
|
15
|
-
Run `
|
105
|
+
Run `npm run c` to build the project. The build artifacts will be stored in the `dist/` directory.
|
16
106
|
|
17
107
|
## Running unit tests
|
18
108
|
|
19
|
-
Run `ng test` to execute the unit tests via [
|
109
|
+
Run `ng test` to execute the unit tests via [Jest](https://jestjs.io/).
|
110
|
+
|
20
111
|
|
21
|
-
##
|
112
|
+
## Features
|
22
113
|
|
23
|
-
|
114
|
+
- Live Stackblitz demoes
|
115
|
+
- [Typedoc with inlined examples](https://fireflysemantics.github.io/slice/doc/)
|
116
|
+
- [Well documented test cases run with Jest - Each file has a corresponding `.spec` file](https://github.com/fireflysemantics/slice/tree/master/src)
|
117
|
+
- Stream both Entity and Object Stores for UI Updates via RxJS
|
118
|
+
- Define entities using Typescript classes, interfaces, or types
|
119
|
+
- [Active state tracking](https://medium.com/@ole.ersoy/monitoring-the-currently-active-entity-with-slice-ff7c9b7826e8)
|
120
|
+
- [Supports for Optimistic User Interfaces](https://medium.com/@ole.ersoy/optimistic-user-identity-management-with-slice-a2b66efe780c)
|
121
|
+
- RESTful API for performing CRUD operations that stream both full and delta updates
|
122
|
+
- Dynamic creation of both object and entity stores
|
123
|
+
- Observable delta updates for Entities
|
124
|
+
- Real time application of Slice `Predicate<E>` filtering that is `Observable`
|
125
|
+
- `Predicate` based snapshots of entities
|
126
|
+
- Observable `count` of entities in the entity store. The `count` feature can also be `Predicate` filtered.
|
127
|
+
- Configurable global id (Client side id - `gid`) and server id (`id`) id property names for entities.
|
128
|
+
- The stream of entities can be sorted via an optional boolean expression passed to `observe`.
|
24
129
|
|
25
|
-
##
|
130
|
+
## Tests
|
26
131
|
|
27
|
-
|
132
|
+
See the [test cases](https://github.com/fireflysemantics/slice/).
|
@@ -0,0 +1,145 @@
|
|
1
|
+
import { ReplaySubject } from 'rxjs';
|
2
|
+
export class OStore {
|
3
|
+
constructor(start) {
|
4
|
+
/**
|
5
|
+
* Map of Key Value pair entries
|
6
|
+
* containing values store in this store.
|
7
|
+
*/
|
8
|
+
this.entries = new Map();
|
9
|
+
/**
|
10
|
+
* Map of replay subject id to `ReplaySubject` instance.
|
11
|
+
*/
|
12
|
+
this.subjects = new Map();
|
13
|
+
if (start) {
|
14
|
+
this.S = start;
|
15
|
+
const keys = Object.keys(start);
|
16
|
+
keys.forEach((k) => {
|
17
|
+
const ovr = start[k];
|
18
|
+
this.post(ovr, ovr.value);
|
19
|
+
ovr.obs = this.observe(ovr);
|
20
|
+
});
|
21
|
+
}
|
22
|
+
}
|
23
|
+
/**
|
24
|
+
* Reset the state of the OStore to the
|
25
|
+
* values or reset provided in the constructor
|
26
|
+
* {@link OStoreStart} instance.
|
27
|
+
*/
|
28
|
+
reset() {
|
29
|
+
if (this.S) {
|
30
|
+
const keys = Object.keys(this.S);
|
31
|
+
keys.forEach((k) => {
|
32
|
+
const ovr = this.S[k];
|
33
|
+
this.put(ovr, ovr.reset ? ovr.reset : ovr.value);
|
34
|
+
});
|
35
|
+
}
|
36
|
+
}
|
37
|
+
/**
|
38
|
+
* Set create a key value pair entry and creates a
|
39
|
+
* corresponding replay subject instance that will
|
40
|
+
* be used to broadcast updates.
|
41
|
+
*
|
42
|
+
* @param key The key identifying the value
|
43
|
+
* @param value The value
|
44
|
+
*/
|
45
|
+
post(key, value) {
|
46
|
+
this.entries.set(key, value);
|
47
|
+
this.subjects.set(key, new ReplaySubject(1));
|
48
|
+
//Emit immediately so that Observers can receive
|
49
|
+
//the value straight away.
|
50
|
+
const subject = this.subjects.get(key);
|
51
|
+
if (subject) {
|
52
|
+
subject.next(value);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
/**
|
56
|
+
* Update a value and notify subscribers.
|
57
|
+
*
|
58
|
+
* @param key
|
59
|
+
* @param value
|
60
|
+
*/
|
61
|
+
put(key, value) {
|
62
|
+
this.entries.set(key, value);
|
63
|
+
const subject = this.subjects.get(key);
|
64
|
+
if (subject) {
|
65
|
+
subject.next(value);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
/**
|
69
|
+
* Deletes both the value entry and the corresponding {@link ReplaySubject}.
|
70
|
+
* Will unsubscribe the {@link ReplaySubject} prior to deleting it,
|
71
|
+
* severing communication with corresponding {@link Observable}s.
|
72
|
+
*
|
73
|
+
* @param key
|
74
|
+
*/
|
75
|
+
delete(key) {
|
76
|
+
//===========================================
|
77
|
+
// Delete the entry
|
78
|
+
//===========================================
|
79
|
+
this.entries.delete(key);
|
80
|
+
const subject = this.subjects.get(key);
|
81
|
+
if (subject) {
|
82
|
+
subject.next(undefined);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
/**
|
86
|
+
* Clear all entries.
|
87
|
+
*
|
88
|
+
* Note that
|
89
|
+
* this will call delete for on all
|
90
|
+
* keys defined which also also
|
91
|
+
* unsubscribes and deletes
|
92
|
+
* all the sbujects.
|
93
|
+
*/
|
94
|
+
clear() {
|
95
|
+
for (let key of this.entries.keys()) {
|
96
|
+
this.delete(key);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
/**
|
100
|
+
* Observe changes to the values.
|
101
|
+
*
|
102
|
+
* @param key
|
103
|
+
* @return An {@link Observable} of the value
|
104
|
+
*/
|
105
|
+
observe(key) {
|
106
|
+
return this.subjects.get(key)
|
107
|
+
? this.subjects.get(key).asObservable()
|
108
|
+
: undefined;
|
109
|
+
}
|
110
|
+
/**
|
111
|
+
* Check whether a value exists.
|
112
|
+
*
|
113
|
+
* @param key
|
114
|
+
* @return True if the entry exists ( Is not null or undefined ) and false otherwise.
|
115
|
+
*/
|
116
|
+
exists(key) {
|
117
|
+
return !!this.entries.get(key);
|
118
|
+
}
|
119
|
+
/**
|
120
|
+
* Retrieve a snapshot of the
|
121
|
+
* value.
|
122
|
+
*
|
123
|
+
* @param key
|
124
|
+
* @return A snapshot of the value corresponding to the key.
|
125
|
+
*/
|
126
|
+
snapshot(key) {
|
127
|
+
return this.entries.get(key);
|
128
|
+
}
|
129
|
+
/**
|
130
|
+
* Indicates whether the store is empty.
|
131
|
+
* @return true if the store is empty, false otherwise.
|
132
|
+
*/
|
133
|
+
isEmpty() {
|
134
|
+
return Array.from(this.entries.values()).length == 0;
|
135
|
+
}
|
136
|
+
/**
|
137
|
+
* Returns the number of key value pairs contained.
|
138
|
+
*
|
139
|
+
* @return the number of entries in the store.
|
140
|
+
*/
|
141
|
+
count() {
|
142
|
+
return Array.from(this.entries.values()).length;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT1N0b3JlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvc2xpY2Uvc3JjL2xpYi9PU3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGFBQWEsRUFBYyxNQUFNLE1BQU0sQ0FBQztBQTJCakQsTUFBTSxPQUFPLE1BQU07SUFPakIsWUFBWSxLQUFrQjtRQTJCOUI7OztXQUdHO1FBQ0ksWUFBTyxHQUFrQixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBRTFDOztXQUVHO1FBQ0ssYUFBUSxHQUFpQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBbkN6RCxJQUFJLEtBQUssRUFBRTtZQUNULElBQUksQ0FBQyxDQUFDLEdBQU0sS0FBSyxDQUFDO1lBQ2xCLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO2dCQUNqQixNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFrQixDQUFDO2dCQUN0QyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQzFCLEdBQUcsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUM5QixDQUFDLENBQUMsQ0FBQztTQUNKO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxLQUFLO1FBQ1YsSUFBSSxJQUFJLENBQUMsQ0FBQyxFQUFFO1lBQ1YsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDakMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO2dCQUNqQixNQUFNLEdBQUcsR0FBa0IsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDckMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ25ELENBQUMsQ0FBQyxDQUFDO1NBQ0o7SUFDSCxDQUFDO0lBYUQ7Ozs7Ozs7T0FPRztJQUNLLElBQUksQ0FBQyxHQUFrQixFQUFFLEtBQVU7UUFDekMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdDLGdEQUFnRDtRQUNoRCwwQkFBMEI7UUFDMUIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkMsSUFBSSxPQUFPLEVBQUU7WUFDWCxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ3JCO0lBQ0gsQ0FBQztJQUNEOzs7OztPQUtHO0lBQ0ksR0FBRyxDQUFDLEdBQVEsRUFBRSxLQUFVO1FBQzdCLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUM3QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QyxJQUFJLE9BQU8sRUFBRTtZQUNYLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDckI7SUFDSCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksTUFBTSxDQUFDLEdBQVE7UUFDcEIsNkNBQTZDO1FBQzdDLG1CQUFtQjtRQUNuQiw2Q0FBNkM7UUFDN0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDekIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkMsSUFBSSxPQUFPLEVBQUU7WUFDWCxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQ3pCO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0ksS0FBSztRQUNWLEtBQUssSUFBSSxHQUFHLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUNqQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ3BCO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksT0FBTyxDQUFDLEdBQVE7UUFDckIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUM7WUFDM0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBRSxDQUFDLFlBQVksRUFBRTtZQUN4QyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQ2hCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxHQUFRO1FBQ3BCLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSSxRQUFRLENBQUMsR0FBUTtRQUN0QixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFRDs7O09BR0c7SUFDSSxPQUFPO1FBQ1osT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksS0FBSztRQUNWLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQ2xELENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFJlcGxheVN1YmplY3QsIE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcblxuLyoqXG4gKiBJbml0aWFsaXplIGh0ZSBzdG9yZSB3aXRoIHRoaXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmFsdWVSZXNldCB7XG4gIHZhbHVlOiBhbnk7XG4gIHJlc2V0PzogYW55O1xufVxuXG4vKipcbiAqIE9TdG9yZSBLZXkgVmFsdWUgUmVzZXRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPYnNWYWx1ZVJlc2V0IHtcbiAgdmFsdWU6IGFueTtcbiAgcmVzZXQ/OiBhbnk7XG4gIG9icz86IE9ic2VydmFibGU8YW55Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBLZXlPYnNWYWx1ZVJlc2V0IHtcbiAgW2tleTogc3RyaW5nXTogT2JzVmFsdWVSZXNldDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPU3RvcmVTdGFydCB7XG4gIFtrZXk6IHN0cmluZ106IFZhbHVlUmVzZXQ7XG59XG5cbmV4cG9ydCBjbGFzcyBPU3RvcmU8RSBleHRlbmRzIEtleU9ic1ZhbHVlUmVzZXQ+IHtcbiAgLyoqXG4gICAqIFN0YXJ0IGtleXMgYW5kIHZhbHVlc1xuICAgKiBwYXNzZWQgaW4gdmlhIGNvbnN0cnVjdG9yLlxuICAgKi9cbiAgcHVibGljIFMhOiBFO1xuXG4gIGNvbnN0cnVjdG9yKHN0YXJ0OiBPU3RvcmVTdGFydCkge1xuICAgIGlmIChzdGFydCkge1xuICAgICAgdGhpcy5TID0gPEU+c3RhcnQ7XG4gICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoc3RhcnQpO1xuICAgICAga2V5cy5mb3JFYWNoKChrKSA9PiB7XG4gICAgICAgIGNvbnN0IG92ciA9IHN0YXJ0W2tdIGFzIE9ic1ZhbHVlUmVzZXQ7XG4gICAgICAgIHRoaXMucG9zdChvdnIsIG92ci52YWx1ZSk7XG4gICAgICAgIG92ci5vYnMgPSB0aGlzLm9ic2VydmUob3ZyKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldCB0aGUgc3RhdGUgb2YgdGhlIE9TdG9yZSB0byB0aGVcbiAgICogdmFsdWVzIG9yIHJlc2V0IHByb3ZpZGVkIGluIHRoZSBjb25zdHJ1Y3RvclxuICAgKiB7QGxpbmsgT1N0b3JlU3RhcnR9IGluc3RhbmNlLlxuICAgKi9cbiAgcHVibGljIHJlc2V0KCkge1xuICAgIGlmICh0aGlzLlMpIHtcbiAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyh0aGlzLlMpO1xuICAgICAga2V5cy5mb3JFYWNoKChrKSA9PiB7XG4gICAgICAgIGNvbnN0IG92cjogT2JzVmFsdWVSZXNldCA9IHRoaXMuU1trXTtcbiAgICAgICAgdGhpcy5wdXQob3ZyLCBvdnIucmVzZXQgPyBvdnIucmVzZXQgOiBvdnIudmFsdWUpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1hcCBvZiBLZXkgVmFsdWUgcGFpciBlbnRyaWVzXG4gICAqIGNvbnRhaW5pbmcgdmFsdWVzIHN0b3JlIGluIHRoaXMgc3RvcmUuXG4gICAqL1xuICBwdWJsaWMgZW50cmllczogTWFwPGFueSwgYW55PiA9IG5ldyBNYXAoKTtcblxuICAvKipcbiAgICogTWFwIG9mIHJlcGxheSBzdWJqZWN0IGlkIHRvIGBSZXBsYXlTdWJqZWN0YCBpbnN0YW5jZS5cbiAgICovXG4gIHByaXZhdGUgc3ViamVjdHM6IE1hcDxhbnksIFJlcGxheVN1YmplY3Q8YW55Pj4gPSBuZXcgTWFwKCk7XG5cbiAgLyoqXG4gICAqIFNldCBjcmVhdGUgYSBrZXkgdmFsdWUgcGFpciBlbnRyeSBhbmQgY3JlYXRlcyBhXG4gICAqIGNvcnJlc3BvbmRpbmcgcmVwbGF5IHN1YmplY3QgaW5zdGFuY2UgdGhhdCB3aWxsXG4gICAqIGJlIHVzZWQgdG8gYnJvYWRjYXN0IHVwZGF0ZXMuXG4gICAqXG4gICAqIEBwYXJhbSBrZXkgVGhlIGtleSBpZGVudGlmeWluZyB0aGUgdmFsdWVcbiAgICogQHBhcmFtIHZhbHVlIFRoZSB2YWx1ZVxuICAgKi9cbiAgcHJpdmF0ZSBwb3N0KGtleTogT2JzVmFsdWVSZXNldCwgdmFsdWU6IGFueSkge1xuICAgIHRoaXMuZW50cmllcy5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgdGhpcy5zdWJqZWN0cy5zZXQoa2V5LCBuZXcgUmVwbGF5U3ViamVjdCgxKSk7XG4gICAgLy9FbWl0IGltbWVkaWF0ZWx5IHNvIHRoYXQgT2JzZXJ2ZXJzIGNhbiByZWNlaXZlXG4gICAgLy90aGUgdmFsdWUgc3RyYWlnaHQgYXdheS5cbiAgICBjb25zdCBzdWJqZWN0ID0gdGhpcy5zdWJqZWN0cy5nZXQoa2V5KTtcbiAgICBpZiAoc3ViamVjdCkge1xuICAgICAgc3ViamVjdC5uZXh0KHZhbHVlKTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIFVwZGF0ZSBhIHZhbHVlIGFuZCBub3RpZnkgc3Vic2NyaWJlcnMuXG4gICAqXG4gICAqIEBwYXJhbSBrZXlcbiAgICogQHBhcmFtIHZhbHVlXG4gICAqL1xuICBwdWJsaWMgcHV0KGtleTogYW55LCB2YWx1ZTogYW55KSB7XG4gICAgdGhpcy5lbnRyaWVzLnNldChrZXksIHZhbHVlKTtcbiAgICBjb25zdCBzdWJqZWN0ID0gdGhpcy5zdWJqZWN0cy5nZXQoa2V5KTtcbiAgICBpZiAoc3ViamVjdCkge1xuICAgICAgc3ViamVjdC5uZXh0KHZhbHVlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyBib3RoIHRoZSB2YWx1ZSBlbnRyeSBhbmQgdGhlIGNvcnJlc3BvbmRpbmcge0BsaW5rIFJlcGxheVN1YmplY3R9LlxuICAgKiBXaWxsIHVuc3Vic2NyaWJlIHRoZSB7QGxpbmsgUmVwbGF5U3ViamVjdH0gcHJpb3IgdG8gZGVsZXRpbmcgaXQsXG4gICAqIHNldmVyaW5nIGNvbW11bmljYXRpb24gd2l0aCBjb3JyZXNwb25kaW5nIHtAbGluayBPYnNlcnZhYmxlfXMuXG4gICAqXG4gICAqIEBwYXJhbSBrZXlcbiAgICovXG4gIHB1YmxpYyBkZWxldGUoa2V5OiBhbnkpIHtcbiAgICAvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBEZWxldGUgdGhlIGVudHJ5XG4gICAgLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgdGhpcy5lbnRyaWVzLmRlbGV0ZShrZXkpO1xuICAgIGNvbnN0IHN1YmplY3QgPSB0aGlzLnN1YmplY3RzLmdldChrZXkpO1xuICAgIGlmIChzdWJqZWN0KSB7XG4gICAgICBzdWJqZWN0Lm5leHQodW5kZWZpbmVkKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2xlYXIgYWxsIGVudHJpZXMuICBcbiAgICogXG4gICAqIE5vdGUgdGhhdCBcbiAgICogdGhpcyB3aWxsIGNhbGwgZGVsZXRlIGZvciBvbiBhbGxcbiAgICoga2V5cyBkZWZpbmVkIHdoaWNoIGFsc28gYWxzbyBcbiAgICogdW5zdWJzY3JpYmVzIGFuZCBkZWxldGVzIFxuICAgKiBhbGwgdGhlIHNidWplY3RzLlxuICAgKi9cbiAgcHVibGljIGNsZWFyKCkge1xuICAgIGZvciAobGV0IGtleSBvZiB0aGlzLmVudHJpZXMua2V5cygpKSB7XG4gICAgICAgIHRoaXMuZGVsZXRlKGtleSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE9ic2VydmUgY2hhbmdlcyB0byB0aGUgdmFsdWVzLlxuICAgKlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEByZXR1cm4gQW4ge0BsaW5rIE9ic2VydmFibGV9IG9mIHRoZSB2YWx1ZVxuICAgKi9cbiAgcHVibGljIG9ic2VydmUoa2V5OiBhbnkpOiBPYnNlcnZhYmxlPGFueT4gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnN1YmplY3RzLmdldChrZXkpXG4gICAgICA/IHRoaXMuc3ViamVjdHMuZ2V0KGtleSkhLmFzT2JzZXJ2YWJsZSgpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayB3aGV0aGVyIGEgdmFsdWUgZXhpc3RzLlxuICAgKlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEByZXR1cm4gVHJ1ZSBpZiB0aGUgZW50cnkgZXhpc3RzICggSXMgbm90IG51bGwgb3IgdW5kZWZpbmVkICkgYW5kIGZhbHNlIG90aGVyd2lzZS5cbiAgICovXG4gIHB1YmxpYyBleGlzdHMoa2V5OiBhbnkpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLmVudHJpZXMuZ2V0KGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmUgYSBzbmFwc2hvdCBvZiB0aGVcbiAgICogdmFsdWUuXG4gICAqXG4gICAqIEBwYXJhbSBrZXlcbiAgICogQHJldHVybiBBIHNuYXBzaG90IG9mIHRoZSB2YWx1ZSBjb3JyZXNwb25kaW5nIHRvIHRoZSBrZXkuXG4gICAqL1xuICBwdWJsaWMgc25hcHNob3Qoa2V5OiBhbnkpOiBhbnkge1xuICAgIHJldHVybiB0aGlzLmVudHJpZXMuZ2V0KGtleSk7XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgdGhlIHN0b3JlIGlzIGVtcHR5LlxuICAgKiBAcmV0dXJuIHRydWUgaWYgdGhlIHN0b3JlIGlzIGVtcHR5LCBmYWxzZSBvdGhlcndpc2UuXG4gICAqL1xuICBwdWJsaWMgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLmVudHJpZXMudmFsdWVzKCkpLmxlbmd0aCA9PSAwO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIG51bWJlciBvZiBrZXkgdmFsdWUgcGFpcnMgY29udGFpbmVkLlxuICAgKlxuICAgKiBAcmV0dXJuIHRoZSBudW1iZXIgb2YgZW50cmllcyBpbiB0aGUgc3RvcmUuXG4gICAqL1xuICBwdWJsaWMgY291bnQoKSB7XG4gICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5lbnRyaWVzLnZhbHVlcygpKS5sZW5ndGg7XG4gIH1cbn1cbiJdfQ==
|