1 | /**
|
2 | * @fileoverview added by tsickle
|
3 | * @suppress {checkTypes} checked by tsc
|
4 | */
|
5 | import * as tslib_1 from "tslib";
|
6 | import { BehaviorSubject, } from 'rxjs';
|
7 | import { distinctUntilChanged, first, } from 'rxjs/operators';
|
8 | import { StateSwitch } from 'state-switch';
|
9 | import { _ModelMutationType, } from '../generated-schemas/';
|
10 | /**
|
11 | * @record
|
12 | */
|
13 | export function StoreSettings() { }
|
14 | function StoreSettings_tsickle_Closure_declarations() {
|
15 | /** @type {?} */
|
16 | StoreSettings.prototype.dataKey;
|
17 | /** @type {?} */
|
18 | StoreSettings.prototype.gqlQueryAll;
|
19 | /** @type {?} */
|
20 | StoreSettings.prototype.gqlSubscribe;
|
21 | }
|
22 | /**
|
23 | * @record
|
24 | */
|
25 | export function StoreAction() { }
|
26 | function StoreAction_tsickle_Closure_declarations() {
|
27 | /** @type {?} */
|
28 | StoreAction.prototype.type;
|
29 | /** @type {?} */
|
30 | StoreAction.prototype.node;
|
31 | }
|
32 | // unsupported: template constraints.
|
33 | // unsupported: template constraints.
|
34 | // unsupported: template constraints.
|
35 | /**
|
36 | * @abstract
|
37 | * @template T, AllItemsQuery, SubscribeItemSubscription
|
38 | */
|
39 | export class Store {
|
40 | /**
|
41 | * @param {?} db
|
42 | * @param {?} settings
|
43 | */
|
44 | constructor(db, settings) {
|
45 | this.db = db;
|
46 | this.settings = settings;
|
47 | this.log = db.log;
|
48 | this.log.verbose('Store', 'constructor()');
|
49 | this.itemList$ = new BehaviorSubject([]);
|
50 | this.itemList = this.itemList$.asObservable().pipe(distinctUntilChanged());
|
51 | this.state = new StateSwitch('Store', this.log);
|
52 | /**
|
53 | * This subscription is for all the life cycle of Store,
|
54 | * we will never need to unsubscribe it.
|
55 | */
|
56 | this.db.apollo.subscribe(apollo => this.refresh(apollo));
|
57 | }
|
58 | /**
|
59 | * @return {?}
|
60 | */
|
61 | open() {
|
62 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
63 | this.log.verbose('Store', 'open()');
|
64 | if (!this.settings) {
|
65 | throw new Error('Store.open() need `this.settings` to be set first!');
|
66 | }
|
67 | if (!this.apollo) {
|
68 | throw new Error('Store.open() apollo not available!');
|
69 | }
|
70 | this.state.on('pending');
|
71 | const /** @type {?} */ hostieQuery = this.apollo.watchQuery({
|
72 | query: this.settings.gqlQueryAll,
|
73 | });
|
74 | this.initSubscribeToMore(hostieQuery);
|
75 | this.itemListSubscription = this.initSubscription(hostieQuery);
|
76 | // await this.initQuery()
|
77 | // await future
|
78 | });
|
79 | }
|
80 | /**
|
81 | * @param {?} apollo
|
82 | * @return {?}
|
83 | */
|
84 | refresh(apollo) {
|
85 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
86 | this.log.verbose('Store', 'refresh(%s)', apollo && apollo.constructor.name);
|
87 | /**
|
88 | * 1. close the existing apollo if it is availble
|
89 | */
|
90 | if (this.apollo) {
|
91 | yield this.close();
|
92 | }
|
93 | this.apollo = apollo;
|
94 | /**
|
95 | * 2. reopen only if the new apollo is available
|
96 | */
|
97 | if (apollo) {
|
98 | yield this.open();
|
99 | }
|
100 | });
|
101 | }
|
102 | /**
|
103 | * @return {?}
|
104 | */
|
105 | close() {
|
106 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
107 | this.log.verbose('Store', 'close()');
|
108 | this.state.off('pending');
|
109 | if (this.itemListSubscription) {
|
110 | this.itemListSubscription.unsubscribe();
|
111 | }
|
112 | this.state.off(true);
|
113 | });
|
114 | }
|
115 | /**
|
116 | * @param {?} itemQuery
|
117 | * @return {?}
|
118 | */
|
119 | initSubscribeToMore(itemQuery) {
|
120 | this.log.verbose('Store', 'initSubscribeToMore(itemQuery)');
|
121 | itemQuery.subscribeToMore({
|
122 | document: this.settings.gqlSubscribe,
|
123 | updateQuery: (prev, { subscriptionData }) => {
|
124 | const /** @type {?} */ data = subscriptionData.data;
|
125 | const /** @type {?} */ dataKey = this.settings.dataKey;
|
126 | // if (!data || !data[dataKey]) {
|
127 | if (!data || !(dataKey in data)) {
|
128 | return prev;
|
129 | }
|
130 | const /** @type {?} */ item = data[dataKey];
|
131 | this.log.silly('Store', 'init() subscribeToMore() updateQuery() prev=%s', JSON.stringify(prev));
|
132 | this.log.silly('Store', 'init() subscribeToMore() updateQuery() data=%s', JSON.stringify(data));
|
133 | const /** @type {?} */ node = item.node;
|
134 | const /** @type {?} */ previousValues = item.previousValues;
|
135 | const /** @type {?} */ newData = /** @type {?} */ (Object.assign({}, prev));
|
136 | newData[dataKey] = this.mutationReducer(newData[dataKey], {
|
137 | type: item.mutation,
|
138 | // MutationType: CREATED / DELETED / UPDATED
|
139 | node: node || previousValues,
|
140 | });
|
141 | return newData;
|
142 | },
|
143 | onError: error => {
|
144 | this.log.warn('Store', 'initSubscribeToMore() onError() %s', JSON.stringify(error));
|
145 | },
|
146 | });
|
147 | }
|
148 | /**
|
149 | * @param {?} itemQuery
|
150 | * @return {?}
|
151 | */
|
152 | initSubscription(itemQuery) {
|
153 | this.log.verbose('Store', 'initSubscription(itemQuery)');
|
154 | const /** @type {?} */ sub = /** @type {?} */ (itemQuery.subscribe(({ data }) => {
|
155 | this.log.silly('Store', 'initSubscription() itemQuery.subscribe() data[dataKey].length=%d', data[this.settings.dataKey].length);
|
156 | this.itemList$.next([...data[this.settings.dataKey]]);
|
157 | /**
|
158 | * issue #12
|
159 | *
|
160 | * wait subscription to be ready before open() returns
|
161 | */
|
162 | this.state.on(true);
|
163 | }));
|
164 | return sub;
|
165 | }
|
166 | /**
|
167 | * @param {?=} state
|
168 | * @param {?=} action
|
169 | * @return {?}
|
170 | */
|
171 | mutationReducer(state = [], action) {
|
172 | this.log.verbose('Store', 'mutationReducer(state.length=%d, action.type=%s)', state.length, action.type);
|
173 | switch (action.type) {
|
174 | case _ModelMutationType.CREATED:
|
175 | state.push(action.node);
|
176 | break;
|
177 | case _ModelMutationType.UPDATED:
|
178 | for (let /** @type {?} */ i = state.length; i--;) {
|
179 | if (state[i].id === action.node.id) {
|
180 | state[i] = action.node;
|
181 | break;
|
182 | }
|
183 | }
|
184 | break;
|
185 | case _ModelMutationType.DELETED:
|
186 | for (let /** @type {?} */ i = state.length; i--;) {
|
187 | if (state[i].id === action.node.id) {
|
188 | state.splice(i, 1);
|
189 | break;
|
190 | }
|
191 | }
|
192 | break;
|
193 | default:
|
194 | throw new Error('unknown action.type:' + action.type);
|
195 | }
|
196 | return state;
|
197 | }
|
198 | /**
|
199 | * @param {?} mutationType
|
200 | * @param {?} mutationDataKey
|
201 | * @return {?}
|
202 | */
|
203 | mutationUpdateFnFactory(mutationType, mutationDataKey) {
|
204 | this.log.verbose('Store', 'mutationUpdateFnFactory(mutationType=%s, mutationDataKey=%s)', mutationType, mutationDataKey);
|
205 | return (proxy, { data }) => {
|
206 | this.log.verbose('Store', 'mutationUpdateFnFactory(mutationType=%s, mutationDataKey=%s) (proxy, {data})', mutationType, mutationDataKey);
|
207 | if (!data) {
|
208 | this.log.verbose('Store', 'mutationUpdateFnFactory() (proxy, {data}) data empty???');
|
209 | return;
|
210 | }
|
211 | let /** @type {?} */ cachedData = null;
|
212 | try {
|
213 | cachedData = proxy.readQuery({ query: this.settings.gqlQueryAll });
|
214 | }
|
215 | catch (/** @type {?} */ e) {
|
216 | this.log.verbose('Store', 'mutationUpdateFnFactory(mutationType=%s, mutationDataKey=%s) (proxy, {data}), %s', mutationType, mutationDataKey, 'call proxy.readQuery() got exceptoin. it mostly like there is no query had been executed before.');
|
217 | }
|
218 | if (!cachedData) {
|
219 | this.log.verbose('Store', 'mutationUpdateFnFactory(mutationType=%s, mutationDataKey=%s) (proxy, {data})proxy.readQuery() return empty???', mutationType, mutationDataKey);
|
220 | return;
|
221 | }
|
222 | const /** @type {?} */ mutationNode = data[mutationDataKey];
|
223 | /**
|
224 | * Combinate all the data to produce a new data
|
225 | */
|
226 | const /** @type {?} */ newData = /** @type {?} */ (Object.assign({}, /** @type {?} */ (cachedData)));
|
227 | newData[this.settings.dataKey] = this.mutationReducer(newData[this.settings.dataKey], {
|
228 | type: mutationType,
|
229 | node: mutationNode,
|
230 | });
|
231 | proxy.writeQuery({ query: this.settings.gqlQueryAll, data: newData });
|
232 | };
|
233 | }
|
234 | /**
|
235 | * CRUD:
|
236 | * 1. create()
|
237 | * 2. read()
|
238 | * 3. update()
|
239 | * 4. delete()
|
240 | * @param {?} id
|
241 | * @return {?}
|
242 | */
|
243 | read(id) {
|
244 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
245 | this.log.verbose('Store', 'read(id=%s)', id);
|
246 | yield this.state.ready();
|
247 | const /** @type {?} */ itemList = yield this.itemList.pipe(first()).toPromise();
|
248 | const /** @type {?} */ result = itemList.filter(i => i['id'] === id);
|
249 | if (result.length !== 1) {
|
250 | throw new Error(`Store.read(id=${id}) not found!`);
|
251 | }
|
252 | return result[0];
|
253 | });
|
254 | }
|
255 | }
|
256 | function Store_tsickle_Closure_declarations() {
|
257 | /** @type {?} */
|
258 | Store.prototype.state;
|
259 | /** @type {?} */
|
260 | Store.prototype.itemListSubscription;
|
261 | /** @type {?} */
|
262 | Store.prototype.apollo;
|
263 | /** @type {?} */
|
264 | Store.prototype.log;
|
265 | /** @type {?} */
|
266 | Store.prototype.itemList$;
|
267 | /** @type {?} */
|
268 | Store.prototype.itemList;
|
269 | /** @type {?} */
|
270 | Store.prototype.db;
|
271 | /** @type {?} */
|
272 | Store.prototype.settings;
|
273 | /**
|
274 | * TO BE IMPLEMENT in the sub class
|
275 | * @abstract
|
276 | * @param {?} id
|
277 | * @return {?}
|
278 | */
|
279 | Store.prototype.delete = function (id) { };
|
280 | /**
|
281 | * @abstract
|
282 | * @param {?} newItem
|
283 | * @return {?}
|
284 | */
|
285 | Store.prototype.create = function (newItem) { };
|
286 | /**
|
287 | * @abstract
|
288 | * @param {?} id
|
289 | * @param {?} props
|
290 | * @return {?}
|
291 | */
|
292 | Store.prototype.update = function (id, props) { };
|
293 | }
|
294 |
|
295 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AY2hhdGllL2RiLyIsInNvdXJjZXMiOlsic3JjL3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQ0EsT0FBTyxFQUNMLGVBQWUsR0FHaEIsTUFBNEIsTUFBTSxDQUFBO0FBQ25DLE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsS0FBSyxHQUNOLE1BQThCLGdCQUFnQixDQUFBO0FBRS9DLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTyxjQUFjLENBQUE7QUFFM0MsT0FBTyxFQUNMLGtCQUFrQixHQUNuQixNQUE0Qix1QkFBdUIsQ0FBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBdUJwRCxNQUFNOzs7OztJQWVKLFlBQ1ksRUFBWSxFQUNaLFFBQXVCO1FBRHZCLE9BQUUsR0FBRixFQUFFLENBQVU7UUFDWixhQUFRLEdBQVIsUUFBUSxDQUFlO1FBRWpDLElBQUksQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQTtRQUVqQixJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUE7UUFFMUMsSUFBSSxDQUFDLFNBQVMsR0FBSSxJQUFJLGVBQWUsQ0FBUSxFQUFFLENBQUMsQ0FBQTtRQUNoRCxJQUFJLENBQUMsUUFBUSxHQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUMsQ0FBQTtRQUU1RSxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksV0FBVyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUE7Ozs7O1FBTS9DLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQTtLQUV6RDs7OztJQUVhLElBQUk7O1lBQ2hCLElBQUks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S0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLGlCQUFpQixFQUFFLGNBQWMsQ0FBQyxDQUFBO2FBQ25EO1lBQ0QsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQTs7O0NBY25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRG9jdW1lbnROb2RlIH0gZnJvbSAnZ3JhcGhxbCdcbmltcG9ydCB7XG4gIEJlaGF2aW9yU3ViamVjdCxcbiAgT2JzZXJ2YWJsZSxcbiAgU3Vic2NyaXB0aW9uLFxufSAgICAgICAgICAgICAgICAgICAgICAgZnJvbSAncnhqcydcbmltcG9ydCB7XG4gIGRpc3RpbmN0VW50aWxDaGFuZ2VkLFxuICBmaXJzdCxcbn0gICAgICAgICAgICAgICAgICAgICAgICAgZnJvbSAncnhqcy9vcGVyYXRvcnMnXG5cbmltcG9ydCB7IFN0YXRlU3dpdGNoIH0gIGZyb20gJ3N0YXRlLXN3aXRjaCdcblxuaW1wb3J0IHtcbiAgX01vZGVsTXV0YXRpb25UeXBlLFxufSAgICAgICAgICAgICAgICAgICAgICAgZnJvbSAnLi4vZ2VuZXJhdGVkLXNjaGVtYXMvJ1xuXG5pbXBvcnQge1xuICBBcG9sbG8sXG4gIERiLFxuICBNdXRhdGlvblVwZGF0ZXJGbixcbiAgT2JzZXJ2YWJsZVF1ZXJ5LFxufSAgICAgICAgICAgICAgICAgICAgIGZyb20gJy4vZGInXG5pbXBvcnQge1xuICBsb2csXG59ICAgICAgICAgICAgICAgICAgICAgZnJvbSAnLi9jb25maWcnXG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RvcmVTZXR0aW5ncyB7XG4gIGRhdGFLZXk6ICAgICAgc3RyaW5nLFxuICBncWxRdWVyeUFsbDogIERvY3VtZW50Tm9kZSxcbiAgZ3FsU3Vic2NyaWJlOiBEb2N1bWVudE5vZGUsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RvcmVBY3Rpb24ge1xuICB0eXBlOiBfTW9kZWxNdXRhdGlvblR5cGUsXG4gIG5vZGU6IGFueSxcbn1cblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFN0b3JlPFxuICBUIGV4dGVuZHMgeyBbaWR4OiBzdHJpbmddOiBhbnkgfSxcbiAgQWxsSXRlbXNRdWVyeSBleHRlbmRzIHsgW2lkeDogc3RyaW5nXTogYW55IH0sXG4gIFN1YnNjcmliZUl0ZW1TdWJzY3JpcHRpb24gZXh0ZW5kcyB7IFtpZHg6IHN0cmluZ106IGFueSB9XG4+IHtcbiAgcHJvdGVjdGVkIHN0YXRlOiBTdGF0ZVN3aXRjaFxuXG4gIHByaXZhdGUgaXRlbUxpc3RTdWJzY3JpcHRpb24/OiBTdWJzY3JpcHRpb25cblxuICBwcm90ZWN0ZWQgYXBvbGxvPzogIEFwb2xsb1xuICBwcm90ZWN0ZWQgbG9nOiAgICAgIHR5cGVvZiBsb2dcblxuICBwcm90ZWN0ZWQgaXRlbUxpc3QkOiAgICBCZWhhdmlvclN1YmplY3Q8IFRbXSA+XG4gIHB1YmxpYyAgICBpdGVtTGlzdDogICAgIE9ic2VydmFibGU8IFRbXSA+XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIGRiOiAgICAgICBEYixcbiAgICBwcm90ZWN0ZWQgc2V0dGluZ3M6IFN0b3JlU2V0dGluZ3MsXG4gICkge1xuICAgIHRoaXMubG9nID0gZGIubG9nXG5cbiAgICB0aGlzLmxvZy52ZXJib3NlKCdTdG9yZScsICdjb25zdHJ1Y3RvcigpJylcblxuICAgIHRoaXMuaXRlbUxpc3QkICA9IG5ldyBCZWhhdmlvclN1YmplY3Q8IFRbXSA+KFtdKVxuICAgIHRoaXMuaXRlbUxpc3QgICA9IHRoaXMuaXRlbUxpc3QkLmFzT2JzZXJ2YWJsZSgpLnBpcGUoZGlzdGluY3RVbnRpbENoYW5nZWQoKSlcblxuICAgIHRoaXMuc3RhdGUgPSBuZXcgU3RhdGVTd2l0Y2goJ1N0b3JlJywgdGhpcy5sb2cpXG5cbiAgICAvKipcbiAgICAgKiBUaGlzIHN1YnNjcmlwdGlvbiBpcyBmb3IgYWxsIHRoZSBsaWZlIGN5Y2xlIG9mIFN0b3JlLFxuICAgICAqIHdlIHdpbGwgbmV2ZXIgbmVlZCB0byB1bnN1YnNjcmliZSBpdC5cbiAgICAgKi9cbiAgICB0aGlzLmRiLmFwb2xsby5zdWJzY3JpYmUoYXBvbGxvID0+IHRoaXMucmVmcmVzaChhcG9sbG8pKVxuXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIG9wZW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5sb2cudmVyYm9zZSgnU3RvcmUnLCAnb3BlbigpJylcbiAgICBpZiAoIXRoaXMuc2V0dGluZ3MpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignU3RvcmUub3BlbigpIG5lZWQgYHRoaXMuc2V0dGluZ3NgIHRvIGJlIHNldCBmaXJzdCEnKVxuICAgIH1cblxuICAgIGlmICghdGhpcy5hcG9sbG8pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignU3RvcmUub3BlbigpIGFwb2xsbyBub3QgYXZhaWxhYmxlIScpXG4gICAgfVxuXG4gICAgdGhpcy5zdGF0ZS5vbigncGVuZGluZycpXG5cbiAgICBjb25zdCBob3N0aWVRdWVyeSA9IHRoaXMuYXBvbGxvLndhdGNoUXVlcnk8QWxsSXRlbXNRdWVyeT4oe1xuICAgICAgcXVlcnk6IHRoaXMuc2V0dGluZ3MuZ3FsUXVlcnlBbGwsXG4gICAgfSlcblxuICAgIHRoaXMuaW5pdFN1YnNjcmliZVRvTW9yZShob3N0aWVRdWVyeSlcbiAgICB0aGlzLml0ZW1MaXN0U3Vic2NyaXB0aW9uID0gdGhpcy5pbml0U3Vic2NyaXB0aW9uKGhvc3RpZVF1ZXJ5KVxuXG4gICAgLy8gYXdhaXQgdGhpcy5pbml0UXVlcnkoKVxuICAgIC8vIGF3YWl0IGZ1dHVyZVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWZyZXNoKGFwb2xsbzogQXBvbGxvIHwgdW5kZWZpbmVkKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5sb2cudmVyYm9zZSgnU3RvcmUnLCAncmVmcmVzaCglcyknLCBhcG9sbG8gJiYgYXBvbGxvLmNvbnN0cnVjdG9yLm5hbWUpXG5cbiAgICAvKipcbiAgICAgKiAxLiBjbG9zZSB0aGUgZXhpc3RpbmcgYXBvbGxvIGlmIGl0IGlzIGF2YWlsYmxlXG4gICAgICovXG4gICAgaWYgKHRoaXMuYXBvbGxvKSB7XG4gICAgICBhd2FpdCB0aGlzLmNsb3NlKClcbiAgICB9XG5cbiAgICB0aGlzLmFwb2xsbyA9IGFwb2xsb1xuXG4gICAgLyoqXG4gICAgICogMi4gcmVvcGVuIG9ubHkgaWYgdGhlIG5ldyBhcG9sbG8gaXMgYXZhaWxhYmxlXG4gICAgICovXG4gICAgaWYgKGFwb2xsbykge1xuICAgICAgYXdhaXQgdGhpcy5vcGVuKClcbiAgICB9XG5cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2xvc2UoKTogICBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmxvZy52ZXJib3NlKCdTdG9yZScsICdjbG9zZSgpJylcblxuICAgIHRoaXMuc3RhdGUub2ZmKCdwZW5kaW5nJylcblxuICAgIGlmICh0aGlzLml0ZW1MaXN0U3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLml0ZW1MaXN0U3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKClcbiAgICB9XG5cbiAgICB0aGlzLnN0YXRlLm9mZih0cnVlKVxuXG4gIH1cblxuICBwcml2YXRlIGluaXRTdWJzY3JpYmVUb01vcmUoaXRlbVF1ZXJ5OiBPYnNlcnZhYmxlUXVlcnk8QWxsSXRlbXNRdWVyeT4pOiB2b2lkIHtcbiAgICB0aGlzLmxvZy52ZXJib3NlKCdTdG9yZScsICdpbml0U3Vic2NyaWJlVG9Nb3JlKGl0ZW1RdWVyeSknKVxuICAgIGl0ZW1RdWVyeS5zdWJzY3JpYmVUb01vcmUoe1xuICAgICAgZG9jdW1lbnQ6IHRoaXMuc2V0dGluZ3MuZ3FsU3Vic2NyaWJlLFxuICAgICAgdXBkYXRlUXVlcnk6IChwcmV2LCB7IHN1YnNjcmlwdGlvbkRhdGEgfSkgPT4ge1xuICAgICAgICBjb25zdCBkYXRhOiBTdWJzY3JpYmVJdGVtU3Vic2NyaXB0aW9uID0gc3Vic2NyaXB0aW9uRGF0YS5kYXRhXG5cbiAgICAgICAgY29uc3QgZGF0YUtleSA9IHRoaXMuc2V0dGluZ3MuZGF0YUtleVxuICAgICAgICAvLyBpZiAoIWRhdGEgfHwgIWRhdGFbZGF0YUtleV0pIHtcbiAgICAgICAgaWYgKCFkYXRhIHx8ICEoZGF0YUtleSBpbiBkYXRhKSkge1xuICAgICAgICAgIHJldHVybiBwcmV2XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpdGVtID0gZGF0YVtkYXRhS2V5XVxuXG4gICAgICAgIHRoaXMubG9nLnNpbGx5KCdTdG9yZScsICdpbml0KCkgc3Vic2NyaWJlVG9Nb3JlKCkgdXBkYXRlUXVlcnkoKSBwcmV2PSVzJywgSlNPTi5zdHJpbmdpZnkocHJldikpXG4gICAgICAgIHRoaXMubG9nLnNpbGx5KCdTdG9yZScsICdpbml0KCkgc3Vic2NyaWJlVG9Nb3JlKCkgdXBkYXRlUXVlcnkoKSBkYXRhPSVzJywgSlNPTi5zdHJpbmdpZnkoZGF0YSkpXG5cbiAgICAgICAgY29uc3Qgbm9kZSAgICAgICAgICAgID0gaXRlbS5ub2RlXG4gICAgICAgIGNvbnN0IHByZXZpb3VzVmFsdWVzICA9IGl0ZW0ucHJldmlvdXNWYWx1ZXNcblxuICAgICAgICBjb25zdCBuZXdEYXRhID0ge1xuICAgICAgICAgIC4uLnByZXYsXG4gICAgICAgIH0gYXMge1xuICAgICAgICAgIFtpZHg6IHN0cmluZ106IGFueSxcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld0RhdGFbZGF0YUtleV0gPSB0aGlzLm11dGF0aW9uUmVkdWNlcihcbiAgICAgICAgICBuZXdEYXRhW2RhdGFLZXldLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IGl0ZW0ubXV0YXRpb24sICAgICAgICAgIC8vIE11dGF0aW9uVHlwZTogQ1JFQVRFRCAvIERFTEVURUQgLyBVUERBVEVEXG4gICAgICAgICAgICBub2RlOiBub2RlIHx8IHByZXZpb3VzVmFsdWVzLCAvLyB3aGVuIERFTEVURSwgbm9kZSB3aWxsIGJlIG51bGwgYW5kIHdlIHVzZSBwcmV2aW91c1ZhbHVlc1xuICAgICAgICAgIH0sXG4gICAgICAgIClcblxuICAgICAgICByZXR1cm4gbmV3RGF0YVxuICAgICAgfSxcbiAgICAgIG9uRXJyb3I6IGVycm9yID0+IHtcbiAgICAgICAgdGhpcy5sb2cud2FybignU3RvcmUnLCAnaW5pdFN1YnNjcmliZVRvTW9yZSgpIG9uRXJyb3IoKSAlcycsIEpTT04uc3RyaW5naWZ5KGVycm9yKSlcbiAgICAgIH0sXG4gICAgfSlcbiAgfVxuXG4gIHByaXZhdGUgaW5pdFN1YnNjcmlwdGlvbihpdGVtUXVlcnk6IE9ic2VydmFibGVRdWVyeTxBbGxJdGVtc1F1ZXJ5Pik6IFN1YnNjcmlwdGlvbiB7XG4gICAgdGhpcy5sb2cudmVyYm9zZSgnU3RvcmUnLCAnaW5pdFN1YnNjcmlwdGlvbihpdGVtUXVlcnkpJylcblxuICAgIGNvbnN0IHN1YiA9IGl0ZW1RdWVyeS5zdWJzY3JpYmUoXG4gICAgICAoeyBkYXRhIH0pID0+IHtcbiAgICAgICAgdGhpcy5sb2cuc2lsbHkoJ1N0b3JlJywgJ2luaXRTdWJzY3JpcHRpb24oKSBpdGVtUXVlcnkuc3Vic2NyaWJlKCkgZGF0YVtkYXRhS2V5XS5sZW5ndGg9JWQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhW3RoaXMuc2V0dGluZ3MuZGF0YUtleV0ubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgdGhpcy5pdGVtTGlzdCQubmV4dChbLi4uZGF0YVt0aGlzLnNldHRpbmdzLmRhdGFLZXldXSlcblxuICAgICAgICAvKipcbiAgICAgICAgICogaXNzdWUgIzEyXG4gICAgICAgICAqXG4gICAgICAgICAqIHdhaXQgc3Vic2NyaXB0aW9uIHRvIGJlIHJlYWR5IGJlZm9yZSBvcGVuKCkgcmV0dXJuc1xuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5zdGF0ZS5vbih0cnVlKVxuICAgICAgfSxcbiAgICApIGFzIFN1YnNjcmlwdGlvblxuXG4gICAgcmV0dXJuIHN1YlxuICB9XG5cbiAgcHJpdmF0ZSBtdXRhdGlvblJlZHVjZXIoXG4gICAgICBzdGF0ZTogIGFueVtdID0gW10sXG4gICAgICBhY3Rpb246IFN0b3JlQWN0aW9uLFxuICApOiBhbnlbXSB7XG4gICAgdGhpcy5sb2cudmVyYm9zZSgnU3RvcmUnLCAnbXV0YXRpb25SZWR1Y2VyKHN0YXRlLmxlbmd0aD0lZCwgYWN0aW9uLnR5cGU9JXMpJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb24udHlwZSxcbiAgICAgICAgICAgICAgICApXG4gICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgY2FzZSBfTW9kZWxNdXRhdGlvblR5cGUuQ1JFQVRFRDpcbiAgICAgICAgc3RhdGUucHVzaChhY3Rpb24ubm9kZSlcbiAgICAgICAgYnJlYWtcblxuICAgICAgY2FzZSBfTW9kZWxNdXRhdGlvblR5cGUuVVBEQVRFRDpcbiAgICAgICAgZm9yIChsZXQgaSA9IHN0YXRlLmxlbmd0aDsgaS0tOykge1xuICAgICAgICAgIGlmIChzdGF0ZVtpXS5pZCA9PT0gYWN0aW9uLm5vZGUuaWQpIHtcbiAgICAgICAgICAgIHN0YXRlW2ldID0gYWN0aW9uLm5vZGVcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrXG5cbiAgICAgIGNhc2UgX01vZGVsTXV0YXRpb25UeXBlLkRFTEVURUQ6XG4gICAgICAgIGZvciAobGV0IGkgPSBzdGF0ZS5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgICBpZiAoc3RhdGVbaV0uaWQgPT09IGFjdGlvbi5ub2RlLmlkKSB7XG4gICAgICAgICAgICBzdGF0ZS5zcGxpY2UoaSwgMSlcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndW5rbm93biBhY3Rpb24udHlwZTonICsgYWN0aW9uLnR5cGUpXG4gICAgfVxuXG4gICAgcmV0dXJuIHN0YXRlXG5cbiAgfVxuXG4gIHByb3RlY3RlZCBtdXRhdGlvblVwZGF0ZUZuRmFjdG9yeShcbiAgICBtdXRhdGlvblR5cGU6ICAgICBfTW9kZWxNdXRhdGlvblR5cGUsXG4gICAgbXV0YXRpb25EYXRhS2V5OiAgc3RyaW5nLFxuICApOiBNdXRhdGlvblVwZGF0ZXJGbjxUPiB7XG4gICAgdGhpcy5sb2cudmVyYm9zZSgnU3RvcmUnLCAnbXV0YXRpb25VcGRhdGVGbkZhY3RvcnkobXV0YXRpb25UeXBlPSVzLCBtdXRhdGlvbkRhdGFLZXk9JXMpJywgbXV0YXRpb25UeXBlLCBtdXRhdGlvbkRhdGFLZXkpXG5cbiAgICByZXR1cm4gKHByb3h5LCB7IGRhdGEgfSkgPT4ge1xuICAgICAgdGhpcy5sb2cudmVyYm9zZSgnU3RvcmUnLCAnbXV0YXRpb25VcGRhdGVGbkZhY3RvcnkobXV0YXRpb25UeXBlPSVzLCBtdXRhdGlvbkRhdGFLZXk9JXMpIChwcm94eSwge2RhdGF9KScsIG11dGF0aW9uVHlwZSwgbXV0YXRpb25EYXRhS2V5KVxuXG4gICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgdGhpcy5sb2cudmVyYm9zZSgnU3RvcmUnLCAnbXV0YXRpb25VcGRhdGVGbkZhY3RvcnkoKSAocHJveHksIHtkYXRhfSkgZGF0YSBlbXB0eT8/PycpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBsZXQgY2FjaGVkRGF0YTogQWxsSXRlbXNRdWVyeSB8IG51bGwgPSBudWxsXG4gICAgICB0cnkge1xuICAgICAgICBjYWNoZWREYXRhID0gcHJveHkucmVhZFF1ZXJ5PEFsbEl0ZW1zUXVlcnk+KHsgcXVlcnk6IHRoaXMuc2V0dGluZ3MuZ3FsUXVlcnlBbGwgfSlcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhpcy5sb2cudmVyYm9zZSgnU3RvcmUnLCAnbXV0YXRpb25VcGRhdGVGbkZhY3RvcnkobXV0YXRpb25UeXBlPSVzLCBtdXRhdGlvbkRhdGFLZXk9JXMpIChwcm94eSwge2RhdGF9KSwgJXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0aW9uVHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGlvbkRhdGFLZXksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NhbGwgcHJveHkucmVhZFF1ZXJ5KCkgZ290IGV4Y2VwdG9pbi4gaXQgbW9zdGx5IGxpa2UgdGhlcmUgaXMgbm8gcXVlcnkgaGFkIGJlZW4gZXhlY3V0ZWQgYmVmb3JlLicpXG4gICAgICB9XG5cbiAgICAgIGlmICghY2FjaGVkRGF0YSkge1xuICAgICAgICB0aGlzLmxvZy52ZXJib3NlKCdTdG9yZScsICdtdXRhdGlvblVwZGF0ZUZuRmFjdG9yeShtdXRhdGlvblR5cGU9JXMsIG11dGF0aW9uRGF0YUtleT0lcykgKHByb3h5LCB7ZGF0YX0pcHJveHkucmVhZFF1ZXJ5KCkgcmV0dXJuIGVtcHR5Pz8/JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGlvblR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRpb25EYXRhS2V5LFxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgY29uc3QgbXV0YXRpb25Ob2RlID0gZGF0YVttdXRhdGlvbkRhdGFLZXldXG5cbiAgICAgIC8qKlxuICAgICAgICogQ29tYmluYXRlIGFsbCB0aGUgZGF0YSB0byBwcm9kdWNlIGEgbmV3IGRhdGFcbiAgICAgICAqL1xuICAgICAgY29uc3QgbmV3RGF0YSA9IHtcbiAgICAgICAgLi4uY2FjaGVkRGF0YSBhcyBPYmplY3QsXG4gICAgICB9IGFzIHtcbiAgICAgICAgW2lkeDogc3RyaW5nXTogYW55LFxuICAgICAgfVxuICAgICAgbmV3RGF0YVt0aGlzLnNldHRpbmdzLmRhdGFLZXldID0gdGhpcy5tdXRhdGlvblJlZHVjZXIoXG4gICAgICAgIG5ld0RhdGFbdGhpcy5zZXR0aW5ncy5kYXRhS2V5XSxcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6IG11dGF0aW9uVHlwZSxcbiAgICAgICAgICBub2RlOiBtdXRhdGlvbk5vZGUsXG4gICAgICAgIH0sXG4gICAgICApXG5cbiAgICAgIHByb3h5LndyaXRlUXVlcnkoeyBxdWVyeTogdGhpcy5zZXR0aW5ncy5ncWxRdWVyeUFsbCwgZGF0YTogbmV3RGF0YSB9KVxuXG4gICAgfVxuICB9XG5cbiAgLy8gcHJpdmF0ZSBhc3luYyBpbml0UXVlcnkoKTogUHJvbWlzZTx2b2lkPiB7XG4gIC8vICAgdGhpcy5sb2cudmVyYm9zZSgnU3RvcmUnLCAnaW5pdFF1ZXJ5KCknKVxuICAvLyAgIGF3YWl0IHRoaXMuZGIuYXBvbGxvLnF1ZXJ5PEFsbEhvc3RpZXNRdWVyeT4oe1xuICAvLyAgICAgcXVlcnk6IEdRTF9RVUVSWV9BTExfSE9TVElFUyxcbiAgLy8gICB9KVxuICAvLyAgIC50aGVuKHggPT4geC5kYXRhLmFsbEhvc3RpZXMpXG4gIC8vICAgLnRoZW4oaG9zdGllTGlzdCA9PiB7XG4gIC8vICAgICBjb25zdCBxdWVyeUl0ZW1NYXA6IEhvc3RpZU1hcCA9IHt9XG4gIC8vICAgICBmb3IgKGNvbnN0IGhvc3RpZSBvZiBob3N0aWVMaXN0KSB7XG4gIC8vICAgICAgIHF1ZXJ5SXRlbU1hcFtob3N0aWUuaWRdID0gaG9zdGllXG4gIC8vICAgICB9XG4gIC8vICAgICB0aGlzLiRpdGVtTWFwLm5leHQocXVlcnlJdGVtTWFwKVxuICAvLyAgIH0pXG4gIC8vIH1cblxuICAvKipcbiAgICogQ1JVRDpcbiAgICogMS4gY3JlYXRlKClcbiAgICogMi4gcmVhZCgpXG4gICAqIDMuIHVwZGF0ZSgpXG4gICAqIDQuIGRlbGV0ZSgpXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVhZChpZDogc3RyaW5nKTogUHJvbWlzZTxUPiB7XG4gICAgdGhpcy5sb2cudmVyYm9zZSgnU3RvcmUnLCAncmVhZChpZD0lcyknLCBpZClcblxuICAgIGF3YWl0IHRoaXMuc3RhdGUucmVhZHkoKVxuXG4gICAgY29uc3QgaXRlbUxpc3QgPSBhd2FpdCB0aGlzLml0ZW1MaXN0LnBpcGUoZmlyc3QoKSkudG9Qcm9taXNlKClcblxuICAgIGNvbnN0IHJlc3VsdCA9IGl0ZW1MaXN0LmZpbHRlcihpID0+IGlbJ2lkJ10gPT09IGlkKVxuICAgIGlmIChyZXN1bHQubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFN0b3JlLnJlYWQoaWQ9JHtpZH0pIG5vdCBmb3VuZCFgKVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0WzBdXG4gIH1cblxuICAvKipcbiAgICogVE8gQkUgSU1QTEVNRU5UIGluIHRoZSBzdWIgY2xhc3NcbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCBhc3luYyBkZWxldGUoaWQ6IHN0cmluZyk6ICAgICAgICAgICBQcm9taXNlPFQ+XG4gIHB1YmxpYyBhYnN0cmFjdCBhc3luYyBjcmVhdGUobmV3SXRlbTogUGFydGlhbDxUPik6ICBQcm9taXNlPFQ+XG4gIHB1YmxpYyBhYnN0cmFjdCBhc3luYyB1cGRhdGUgKFxuICAgIGlkOiAgICAgc3RyaW5nLFxuICAgIHByb3BzOiAgVCxcbiAgKTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFByb21pc2U8VD5cblxuICAvLyBzZWFyY2g6IChjb25kOiBhbnkpID0+IFByb21pc2U8W1RdPixcbn1cbiJdfQ== |
\ | No newline at end of file |