@quantiya/codevibe-core 1.0.0

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 (49) hide show
  1. package/README.md +178 -0
  2. package/bin/codevibe.js +7 -0
  3. package/dist/appsync/appsync-client.d.ts +132 -0
  4. package/dist/appsync/appsync-client.js +568 -0
  5. package/dist/appsync/index.d.ts +2 -0
  6. package/dist/appsync/index.js +10 -0
  7. package/dist/appsync/queries.d.ts +16 -0
  8. package/dist/appsync/queries.js +189 -0
  9. package/dist/auth/auth-cli.d.ts +5 -0
  10. package/dist/auth/auth-cli.js +217 -0
  11. package/dist/auth/auth-service.d.ts +53 -0
  12. package/dist/auth/auth-service.js +310 -0
  13. package/dist/auth/index.d.ts +2 -0
  14. package/dist/auth/index.js +9 -0
  15. package/dist/config/config.d.ts +53 -0
  16. package/dist/config/config.js +123 -0
  17. package/dist/config/index.d.ts +2 -0
  18. package/dist/config/index.js +8 -0
  19. package/dist/crypto/crypto-service.d.ts +118 -0
  20. package/dist/crypto/crypto-service.js +284 -0
  21. package/dist/crypto/index.d.ts +1 -0
  22. package/dist/crypto/index.js +9 -0
  23. package/dist/index.d.ts +14 -0
  24. package/dist/index.js +68 -0
  25. package/dist/keychain/index.d.ts +1 -0
  26. package/dist/keychain/index.js +8 -0
  27. package/dist/keychain/keychain-manager.d.ts +125 -0
  28. package/dist/keychain/keychain-manager.js +375 -0
  29. package/dist/logger/index.d.ts +1 -0
  30. package/dist/logger/index.js +8 -0
  31. package/dist/logger/logger.d.ts +35 -0
  32. package/dist/logger/logger.js +142 -0
  33. package/dist/prompt-parser.d.ts +39 -0
  34. package/dist/prompt-parser.js +236 -0
  35. package/dist/session/index.d.ts +2 -0
  36. package/dist/session/index.js +7 -0
  37. package/dist/session/session-resume.d.ts +55 -0
  38. package/dist/session/session-resume.js +151 -0
  39. package/dist/types/auth.d.ts +15 -0
  40. package/dist/types/auth.js +3 -0
  41. package/dist/types/encryption.d.ts +54 -0
  42. package/dist/types/encryption.js +3 -0
  43. package/dist/types/events.d.ts +74 -0
  44. package/dist/types/events.js +28 -0
  45. package/dist/types/index.d.ts +4 -0
  46. package/dist/types/index.js +22 -0
  47. package/dist/types/session.d.ts +59 -0
  48. package/dist/types/session.js +22 -0
  49. package/package.json +51 -0
@@ -0,0 +1,568 @@
1
+ "use strict";
2
+ //
3
+ // appsync-client.ts
4
+ // CodeVibe Core
5
+ //
6
+ // GraphQL client for AWS AppSync with WebSocket subscriptions
7
+ //
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AppSyncClient = void 0;
13
+ const ws_1 = __importDefault(require("ws"));
14
+ const uuid_1 = require("uuid");
15
+ const config_1 = require("../config");
16
+ const logger_1 = require("../logger");
17
+ const keychain_1 = require("../keychain");
18
+ const queries_1 = require("./queries");
19
+ const types_1 = require("../types");
20
+ /**
21
+ * Reconnection configuration — two-phase strategy:
22
+ * Phase 1 (urgent): Exponential backoff 1s → 60s for first 10 attempts
23
+ * Phase 2 (persistent): Retry every 5 minutes indefinitely
24
+ */
25
+ const RECONNECT_CONFIG = {
26
+ urgentMaxAttempts: 10,
27
+ baseDelayMs: 1000,
28
+ maxDelayMs: 60000,
29
+ backoffMultiplier: 2,
30
+ persistentDelayMs: 5 * 60 * 1000, // 5 minutes
31
+ };
32
+ /**
33
+ * AppSync GraphQL client with WebSocket subscriptions
34
+ */
35
+ class AppSyncClient {
36
+ constructor() {
37
+ this.authenticated = false;
38
+ this.currentUserId = null;
39
+ this.currentEmail = null;
40
+ this.tokens = null;
41
+ this.activeSubscriptions = new Map();
42
+ // MARK: - Heartbeat
43
+ this.heartbeatTimers = new Map();
44
+ // Get environment from centralized config (reads process.env.ENVIRONMENT)
45
+ this.environment = (0, config_1.getEnvironment)();
46
+ logger_1.logger.info('[AppSyncClient] Initialized', { environment: this.environment });
47
+ }
48
+ /**
49
+ * Get the current authenticated user ID
50
+ */
51
+ getCurrentUserId() {
52
+ if (!this.currentUserId) {
53
+ throw new Error('Not authenticated. Call authenticateWithStoredTokens() first.');
54
+ }
55
+ return this.currentUserId;
56
+ }
57
+ /**
58
+ * Get the current authenticated user email
59
+ */
60
+ getCurrentUserEmail() {
61
+ return this.currentEmail;
62
+ }
63
+ /**
64
+ * Authenticate using stored OAuth tokens from keychain
65
+ */
66
+ async authenticateWithStoredTokens() {
67
+ try {
68
+ const tokens = await keychain_1.keychainManager.getTokens(this.environment);
69
+ if (!tokens) {
70
+ logger_1.logger.debug('[AppSyncClient] No stored tokens found');
71
+ return false;
72
+ }
73
+ logger_1.logger.info('[AppSyncClient] Found stored OAuth tokens', {
74
+ userId: tokens.userId,
75
+ email: tokens.email,
76
+ expired: keychain_1.keychainManager.isTokenExpired(tokens),
77
+ });
78
+ // If tokens are expired, try to refresh them
79
+ if (keychain_1.keychainManager.isTokenExpired(tokens)) {
80
+ logger_1.logger.info('[AppSyncClient] Tokens expired, attempting refresh...');
81
+ const refreshed = await this.refreshTokens(tokens);
82
+ if (!refreshed) {
83
+ logger_1.logger.warn('[AppSyncClient] Token refresh failed');
84
+ return false;
85
+ }
86
+ }
87
+ else {
88
+ this.tokens = tokens;
89
+ }
90
+ this.currentUserId = this.tokens.userId;
91
+ this.currentEmail = this.tokens.email;
92
+ this.authenticated = true;
93
+ logger_1.logger.info('[AppSyncClient] Authenticated successfully', {
94
+ userId: this.currentUserId,
95
+ email: this.currentEmail,
96
+ });
97
+ return true;
98
+ }
99
+ catch (error) {
100
+ logger_1.logger.error('[AppSyncClient] Authentication failed:', error);
101
+ return false;
102
+ }
103
+ }
104
+ /**
105
+ * Refresh expired tokens
106
+ */
107
+ async refreshTokens(tokens) {
108
+ try {
109
+ const config = (0, config_1.getConfig)();
110
+ const tokenUrl = `https://${config.aws.cognitoDomain}/oauth2/token`;
111
+ const params = new URLSearchParams({
112
+ grant_type: 'refresh_token',
113
+ client_id: config.aws.cognitoClientId,
114
+ refresh_token: tokens.refreshToken,
115
+ });
116
+ const response = await fetch(tokenUrl, {
117
+ method: 'POST',
118
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
119
+ body: params.toString(),
120
+ });
121
+ if (!response.ok) {
122
+ logger_1.logger.error('[AppSyncClient] Token refresh failed', { status: response.status });
123
+ return false;
124
+ }
125
+ const data = await response.json();
126
+ const updatedTokens = {
127
+ ...tokens,
128
+ accessToken: data.access_token,
129
+ idToken: data.id_token,
130
+ expiresAt: Date.now() + (data.expires_in * 1000),
131
+ };
132
+ await keychain_1.keychainManager.setTokens(updatedTokens, this.environment);
133
+ this.tokens = updatedTokens;
134
+ logger_1.logger.info('[AppSyncClient] Tokens refreshed', {
135
+ expiresAt: new Date(updatedTokens.expiresAt).toISOString(),
136
+ });
137
+ return true;
138
+ }
139
+ catch (error) {
140
+ logger_1.logger.error('[AppSyncClient] Token refresh error:', error);
141
+ return false;
142
+ }
143
+ }
144
+ /**
145
+ * Check if authenticated
146
+ */
147
+ isAuthenticated() {
148
+ return this.authenticated;
149
+ }
150
+ /**
151
+ * Sign out
152
+ */
153
+ signOut() {
154
+ this.authenticated = false;
155
+ this.tokens = null;
156
+ this.currentUserId = null;
157
+ this.currentEmail = null;
158
+ this.cleanupSubscriptions();
159
+ logger_1.logger.info('[AppSyncClient] Signed out');
160
+ }
161
+ /**
162
+ * Make a GraphQL request
163
+ */
164
+ async graphqlRequest(query, variables, isRetry = false) {
165
+ const config = (0, config_1.getConfig)();
166
+ if (!this.tokens?.idToken) {
167
+ throw new Error('Not authenticated. Run "codevibe login" first.');
168
+ }
169
+ const headers = {
170
+ 'Content-Type': 'application/json',
171
+ 'Authorization': this.tokens.idToken,
172
+ };
173
+ const response = await fetch(config.aws.appsyncUrl, {
174
+ method: 'POST',
175
+ headers,
176
+ body: JSON.stringify({ query, variables }),
177
+ });
178
+ const result = await response.json();
179
+ // Handle 401 with token refresh
180
+ if (response.status === 401 && !isRetry && this.tokens) {
181
+ logger_1.logger.info('[AppSyncClient] 401 Unauthorized, refreshing token...');
182
+ const refreshed = await this.refreshTokens(this.tokens);
183
+ if (refreshed) {
184
+ return this.graphqlRequest(query, variables, true);
185
+ }
186
+ throw new Error('Token expired and refresh failed');
187
+ }
188
+ if (!response.ok) {
189
+ throw new Error(`GraphQL request failed: ${response.status}`);
190
+ }
191
+ if (result.errors?.length) {
192
+ throw new Error(`GraphQL error: ${result.errors[0].message}`);
193
+ }
194
+ return result;
195
+ }
196
+ // MARK: - Session Operations
197
+ /**
198
+ * Create a session
199
+ */
200
+ async createSession(input) {
201
+ const preparedInput = {
202
+ ...input,
203
+ metadata: input.metadata ? JSON.stringify(input.metadata) : undefined,
204
+ };
205
+ const response = await this.graphqlRequest(queries_1.mutations.createSession, { input: preparedInput });
206
+ logger_1.logger.info('[AppSyncClient] Session created', { sessionId: response.data.createSession.sessionId });
207
+ return response.data.createSession;
208
+ }
209
+ /**
210
+ * Update a session
211
+ */
212
+ async updateSession(input) {
213
+ const preparedInput = {
214
+ ...input,
215
+ metadata: input.metadata ? JSON.stringify(input.metadata) : undefined,
216
+ };
217
+ const response = await this.graphqlRequest(queries_1.mutations.updateSession, { input: preparedInput });
218
+ logger_1.logger.debug('[AppSyncClient] Session updated', { sessionId: response.data.updateSession.sessionId });
219
+ return response.data.updateSession;
220
+ }
221
+ /**
222
+ * Get a session
223
+ */
224
+ async getSession(sessionId) {
225
+ const response = await this.graphqlRequest(queries_1.queries.getSession, { sessionId });
226
+ return response.data.getSession;
227
+ }
228
+ // MARK: - Event Operations
229
+ /**
230
+ * Create an event
231
+ */
232
+ async createEvent(input) {
233
+ const preparedInput = {
234
+ ...input,
235
+ metadata: input.metadata ? JSON.stringify(input.metadata) : undefined,
236
+ };
237
+ const response = await this.graphqlRequest(queries_1.mutations.createEvent, { input: preparedInput });
238
+ logger_1.logger.debug('[AppSyncClient] Event created', {
239
+ eventId: response.data.createEvent.eventId,
240
+ type: response.data.createEvent.type,
241
+ });
242
+ return response.data.createEvent;
243
+ }
244
+ /**
245
+ * Update event status
246
+ */
247
+ async updateEventStatus(input) {
248
+ const response = await this.graphqlRequest(queries_1.mutations.updateEventStatus, { input });
249
+ return response.data.updateEventStatus;
250
+ }
251
+ /**
252
+ * List events for a session
253
+ */
254
+ async listEvents(sessionId, source, limit) {
255
+ const response = await this.graphqlRequest(queries_1.queries.listEvents, { sessionId, source, limit });
256
+ return response.data.listEvents.items;
257
+ }
258
+ // MARK: - Device Key Operations
259
+ /**
260
+ * List user device keys
261
+ */
262
+ async listUserDeviceKeys() {
263
+ const response = await this.graphqlRequest(queries_1.queries.listUserDeviceKeys, {});
264
+ return response.data.listUserDeviceKeys || [];
265
+ }
266
+ /**
267
+ * Register device key
268
+ */
269
+ async registerDeviceKey(deviceId, publicKey, platform, deviceName) {
270
+ const input = { deviceId, publicKey, platform, deviceName };
271
+ await this.graphqlRequest(queries_1.mutations.registerDeviceKey, { input });
272
+ logger_1.logger.info('[AppSyncClient] Device key registered', { deviceId, platform });
273
+ }
274
+ // MARK: - Attachment Operations
275
+ /**
276
+ * Get attachment download URL
277
+ */
278
+ async getAttachmentDownloadUrl(s3Key) {
279
+ const response = await this.graphqlRequest(queries_1.mutations.getAttachmentDownloadUrl, { s3Key });
280
+ return response.data.getAttachmentDownloadUrl;
281
+ }
282
+ // MARK: - Subscriptions
283
+ /**
284
+ * Subscribe to events for a session
285
+ */
286
+ subscribeToEvents(sessionId, onEvent, onError) {
287
+ logger_1.logger.info('[AppSyncClient] Subscribing to events', { sessionId });
288
+ // Cleanup existing subscription
289
+ const existing = this.activeSubscriptions.get(sessionId);
290
+ if (existing) {
291
+ this.cleanupSubscriptionState(existing);
292
+ this.activeSubscriptions.delete(sessionId);
293
+ }
294
+ const state = {
295
+ ws: null,
296
+ subscriptionId: (0, uuid_1.v4)(),
297
+ sessionId,
298
+ onEvent,
299
+ onError,
300
+ reconnectAttempts: 0,
301
+ isReconnecting: false,
302
+ };
303
+ this.activeSubscriptions.set(sessionId, state);
304
+ this.createSubscription(state);
305
+ return () => {
306
+ this.cleanupSubscriptionState(state);
307
+ this.activeSubscriptions.delete(sessionId);
308
+ };
309
+ }
310
+ /**
311
+ * Build WebSocket URL
312
+ */
313
+ buildRealtimeUrl() {
314
+ const config = (0, config_1.getConfig)();
315
+ const realtimeUrl = config.aws.appsyncUrl
316
+ .replace('https://', 'wss://')
317
+ .replace('appsync-api', 'appsync-realtime-api');
318
+ const authHeader = {
319
+ host: new URL(config.aws.appsyncUrl).host,
320
+ };
321
+ if (this.tokens?.idToken) {
322
+ authHeader['Authorization'] = this.tokens.idToken;
323
+ }
324
+ const headerBase64 = Buffer.from(JSON.stringify(authHeader)).toString('base64');
325
+ const payloadBase64 = Buffer.from(JSON.stringify({})).toString('base64');
326
+ return `${realtimeUrl}?header=${headerBase64}&payload=${payloadBase64}`;
327
+ }
328
+ /**
329
+ * Create WebSocket subscription
330
+ */
331
+ createSubscription(state) {
332
+ const { sessionId, subscriptionId, onEvent, onError } = state;
333
+ try {
334
+ const wsUrl = this.buildRealtimeUrl();
335
+ const ws = new ws_1.default(wsUrl, ['graphql-ws']);
336
+ ws.on('open', () => {
337
+ logger_1.logger.info('[AppSyncClient] WebSocket connected', { sessionId });
338
+ ws.send(JSON.stringify({ type: 'connection_init' }));
339
+ });
340
+ ws.on('message', (data) => {
341
+ try {
342
+ const message = JSON.parse(data.toString());
343
+ switch (message.type) {
344
+ case 'connection_ack':
345
+ this.sendSubscriptionStart(ws, state);
346
+ break;
347
+ case 'start_ack':
348
+ logger_1.logger.info('[AppSyncClient] Subscription started', { sessionId });
349
+ state.isReconnecting = false;
350
+ state.reconnectAttempts = 0;
351
+ break;
352
+ case 'data':
353
+ this.resetKeepAliveTimer(state);
354
+ const event = message.payload?.data?.onEventCreated;
355
+ if (event && event.source === types_1.EventSource.MOBILE) {
356
+ onEvent(event);
357
+ }
358
+ break;
359
+ case 'ka':
360
+ this.resetKeepAliveTimer(state);
361
+ break;
362
+ case 'error':
363
+ const errorMsg = message.payload?.errors?.[0]?.message || 'Unknown error';
364
+ this.handleSubscriptionError(state, new Error(errorMsg));
365
+ break;
366
+ }
367
+ }
368
+ catch (e) {
369
+ logger_1.logger.error('[AppSyncClient] Failed to parse message', { error: e });
370
+ }
371
+ });
372
+ ws.on('error', (error) => {
373
+ logger_1.logger.error('[AppSyncClient] WebSocket error', { sessionId, error: error.message });
374
+ this.handleSubscriptionError(state, error);
375
+ });
376
+ ws.on('close', (code, reason) => {
377
+ logger_1.logger.info('[AppSyncClient] WebSocket closed', { sessionId, code });
378
+ if (state.keepAliveTimer) {
379
+ clearTimeout(state.keepAliveTimer);
380
+ }
381
+ if (code !== 1000 && this.activeSubscriptions.has(sessionId)) {
382
+ this.handleSubscriptionError(state, new Error(`WebSocket closed: ${code}`));
383
+ }
384
+ });
385
+ state.ws = ws;
386
+ this.resetKeepAliveTimer(state);
387
+ }
388
+ catch (error) {
389
+ this.handleSubscriptionError(state, error);
390
+ }
391
+ }
392
+ /**
393
+ * Send subscription start message
394
+ */
395
+ sendSubscriptionStart(ws, state) {
396
+ const config = (0, config_1.getConfig)();
397
+ const { sessionId, subscriptionId } = state;
398
+ const authHeader = {
399
+ host: new URL(config.aws.appsyncUrl).host,
400
+ };
401
+ if (this.tokens?.idToken) {
402
+ authHeader['Authorization'] = this.tokens.idToken;
403
+ }
404
+ ws.send(JSON.stringify({
405
+ id: subscriptionId,
406
+ type: 'start',
407
+ payload: {
408
+ data: JSON.stringify({
409
+ query: queries_1.subscriptions.onEventCreated,
410
+ variables: { sessionId },
411
+ }),
412
+ extensions: { authorization: authHeader },
413
+ },
414
+ }));
415
+ }
416
+ /**
417
+ * Reset keep-alive timer
418
+ */
419
+ resetKeepAliveTimer(state) {
420
+ if (state.keepAliveTimer) {
421
+ clearTimeout(state.keepAliveTimer);
422
+ }
423
+ state.keepAliveTimer = setTimeout(() => {
424
+ this.handleSubscriptionError(state, new Error('Keep-alive timeout'));
425
+ }, 5 * 60 * 1000);
426
+ }
427
+ /**
428
+ * Handle subscription error with two-phase reconnection:
429
+ * Phase 1 (urgent): Exponential backoff for first N attempts
430
+ * Phase 2 (persistent): Fixed interval retry indefinitely
431
+ */
432
+ handleSubscriptionError(state, error) {
433
+ const { sessionId, onError } = state;
434
+ if (state.isReconnecting || !this.activeSubscriptions.has(sessionId)) {
435
+ return;
436
+ }
437
+ state.isReconnecting = true;
438
+ state.reconnectAttempts++;
439
+ const isUrgentPhase = state.reconnectAttempts <= RECONNECT_CONFIG.urgentMaxAttempts;
440
+ let delay;
441
+ if (isUrgentPhase) {
442
+ delay = Math.min(RECONNECT_CONFIG.baseDelayMs * Math.pow(RECONNECT_CONFIG.backoffMultiplier, state.reconnectAttempts - 1), RECONNECT_CONFIG.maxDelayMs);
443
+ }
444
+ else {
445
+ delay = RECONNECT_CONFIG.persistentDelayMs;
446
+ if (state.reconnectAttempts === RECONNECT_CONFIG.urgentMaxAttempts + 1) {
447
+ logger_1.logger.info('[AppSyncClient] Switching to persistent reconnect (every 5min)', { sessionId });
448
+ }
449
+ }
450
+ logger_1.logger.info('[AppSyncClient] Scheduling reconnect', {
451
+ sessionId,
452
+ attempt: state.reconnectAttempts,
453
+ phase: isUrgentPhase ? 'urgent' : 'persistent',
454
+ delayMs: delay,
455
+ });
456
+ if (state.ws) {
457
+ try {
458
+ state.ws.close(1000);
459
+ }
460
+ catch (e) { /* ignore */ }
461
+ state.ws = null;
462
+ }
463
+ if (state.keepAliveTimer) {
464
+ clearTimeout(state.keepAliveTimer);
465
+ }
466
+ state.reconnectTimer = setTimeout(async () => {
467
+ // Reset flag so next failure can trigger another reconnect
468
+ state.isReconnecting = false;
469
+ if (!this.activeSubscriptions.has(sessionId)) {
470
+ return;
471
+ }
472
+ // Refresh tokens before reconnecting — they may have expired
473
+ try {
474
+ const freshTokens = await keychain_1.keychainManager.getTokens(this.environment);
475
+ if (freshTokens) {
476
+ if (keychain_1.keychainManager.isTokenExpired(freshTokens)) {
477
+ const refreshed = await this.refreshTokens(freshTokens);
478
+ if (refreshed) {
479
+ logger_1.logger.info('[AppSyncClient] Tokens refreshed before reconnect', { sessionId });
480
+ }
481
+ }
482
+ else {
483
+ this.tokens = freshTokens;
484
+ }
485
+ }
486
+ }
487
+ catch (e) {
488
+ logger_1.logger.warn('[AppSyncClient] Token refresh failed before reconnect, using existing tokens', { sessionId });
489
+ }
490
+ state.subscriptionId = (0, uuid_1.v4)();
491
+ this.createSubscription(state);
492
+ }, delay);
493
+ }
494
+ /**
495
+ * Cleanup subscription state
496
+ */
497
+ cleanupSubscriptionState(state) {
498
+ if (state.reconnectTimer) {
499
+ clearTimeout(state.reconnectTimer);
500
+ }
501
+ if (state.keepAliveTimer) {
502
+ clearTimeout(state.keepAliveTimer);
503
+ }
504
+ if (state.ws) {
505
+ try {
506
+ if (state.ws.readyState === ws_1.default.OPEN) {
507
+ state.ws.send(JSON.stringify({ id: state.subscriptionId, type: 'stop' }));
508
+ state.ws.close(1000);
509
+ }
510
+ }
511
+ catch (e) { /* ignore */ }
512
+ state.ws = null;
513
+ }
514
+ }
515
+ /**
516
+ * Start periodic heartbeat for a session.
517
+ * Updates lastHeartbeatAt on the session every intervalMs (default 2 minutes).
518
+ */
519
+ startHeartbeat(sessionId, intervalMs = 2 * 60 * 1000) {
520
+ this.stopHeartbeat(sessionId);
521
+ // Send initial heartbeat immediately
522
+ this.sendHeartbeat(sessionId);
523
+ const timer = setInterval(() => {
524
+ this.sendHeartbeat(sessionId);
525
+ }, intervalMs);
526
+ this.heartbeatTimers.set(sessionId, timer);
527
+ logger_1.logger.info('[AppSyncClient] Heartbeat started', { sessionId, intervalMs });
528
+ }
529
+ /**
530
+ * Stop heartbeat for a session.
531
+ */
532
+ stopHeartbeat(sessionId) {
533
+ const timer = this.heartbeatTimers.get(sessionId);
534
+ if (timer) {
535
+ clearInterval(timer);
536
+ this.heartbeatTimers.delete(sessionId);
537
+ logger_1.logger.info('[AppSyncClient] Heartbeat stopped', { sessionId });
538
+ }
539
+ }
540
+ /**
541
+ * Send a single heartbeat update.
542
+ */
543
+ async sendHeartbeat(sessionId) {
544
+ try {
545
+ await this.updateSession({
546
+ sessionId,
547
+ lastHeartbeatAt: new Date().toISOString(),
548
+ });
549
+ logger_1.logger.debug('[AppSyncClient] Heartbeat sent', { sessionId });
550
+ }
551
+ catch (error) {
552
+ logger_1.logger.warn('[AppSyncClient] Heartbeat failed', { sessionId, error });
553
+ }
554
+ }
555
+ /**
556
+ * Cleanup all subscriptions and heartbeats
557
+ */
558
+ cleanupSubscriptions() {
559
+ this.activeSubscriptions.forEach((state) => {
560
+ this.cleanupSubscriptionState(state);
561
+ });
562
+ this.activeSubscriptions.clear();
563
+ this.heartbeatTimers.forEach((timer) => clearInterval(timer));
564
+ this.heartbeatTimers.clear();
565
+ }
566
+ }
567
+ exports.AppSyncClient = AppSyncClient;
568
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwc3luYy1jbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBwc3luYy9hcHBzeW5jLWNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsRUFBRTtBQUNGLG9CQUFvQjtBQUNwQixnQkFBZ0I7QUFDaEIsRUFBRTtBQUNGLDhEQUE4RDtBQUM5RCxFQUFFOzs7Ozs7QUFFRiw0Q0FBMkI7QUFDM0IsK0JBQW9DO0FBQ3BDLHNDQUFzRDtBQUN0RCxzQ0FBbUM7QUFDbkMsMENBQThDO0FBQzlDLHVDQUE4RDtBQUM5RCxvQ0FVa0I7QUF5QmxCOzs7O0dBSUc7QUFDSCxNQUFNLGdCQUFnQixHQUFHO0lBQ3ZCLGlCQUFpQixFQUFFLEVBQUU7SUFDckIsV0FBVyxFQUFFLElBQUk7SUFDakIsVUFBVSxFQUFFLEtBQUs7SUFDakIsaUJBQWlCLEVBQUUsQ0FBQztJQUNwQixpQkFBaUIsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksRUFBRSxZQUFZO0NBQy9DLENBQUM7QUFFRjs7R0FFRztBQUNILE1BQWEsYUFBYTtJQVF4QjtRQVBRLGtCQUFhLEdBQVksS0FBSyxDQUFDO1FBQy9CLGtCQUFhLEdBQWtCLElBQUksQ0FBQztRQUNwQyxpQkFBWSxHQUFrQixJQUFJLENBQUM7UUFDbkMsV0FBTSxHQUFxQixJQUFJLENBQUM7UUFDaEMsd0JBQW1CLEdBQW1DLElBQUksR0FBRyxFQUFFLENBQUM7UUFxakJ4RSxvQkFBb0I7UUFFWixvQkFBZSxHQUFnQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBbmpCL0QsMEVBQTBFO1FBQzFFLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBQSx1QkFBYyxHQUFFLENBQUM7UUFDcEMsZUFBTSxDQUFDLElBQUksQ0FBQyw2QkFBNkIsRUFBRSxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUNoRixDQUFDO0lBRUQ7O09BRUc7SUFDSSxnQkFBZ0I7UUFDckIs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QUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsZUFBTSxDQUFDLElBQUksQ0FBQyxrQ0FBa0MsRUFBRSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3hFLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxvQkFBb0I7UUFDekIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ3pDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2QyxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUVqQyxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUMvQixDQUFDO0NBQ0Y7QUF2bkJELHNDQXVuQkMiLCJzb3VyY2VzQ29udGVudCI6WyIvL1xuLy8gYXBwc3luYy1jbGllbnQudHNcbi8vIENvZGVWaWJlIENvcmVcbi8vXG4vLyBHcmFwaFFMIGNsaWVudCBmb3IgQVdTIEFwcFN5bmMgd2l0aCBXZWJTb2NrZXQgc3Vic2NyaXB0aW9uc1xuLy9cblxuaW1wb3J0IFdlYlNvY2tldCBmcm9tICd3cyc7XG5pbXBvcnQgeyB2NCBhcyB1dWlkdjQgfSBmcm9tICd1dWlkJztcbmltcG9ydCB7IGdldENvbmZpZywgZ2V0RW52aXJvbm1lbnQgfSBmcm9tICcuLi9jb25maWcnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyJztcbmltcG9ydCB7IGtleWNoYWluTWFuYWdlciB9IGZyb20gJy4uL2tleWNoYWluJztcbmltcG9ydCB7IHF1ZXJpZXMsIG11dGF0aW9ucywgc3Vic2NyaXB0aW9ucyB9IGZyb20gJy4vcXVlcmllcyc7XG5pbXBvcnQge1xuICBDcmVhdGVFdmVudElucHV0LFxuICBDcmVhdGVTZXNzaW9uSW5wdXQsXG4gIFVwZGF0ZVNlc3Npb25JbnB1dCxcbiAgVXBkYXRlRXZlbnRTdGF0dXNJbnB1dCxcbiAgRXZlbnQsXG4gIFNlc3Npb24sXG4gIEV2ZW50U291cmNlLFxuICBEZXZpY2VLZXksXG4gIFRva2VuRGF0YSxcbn0gZnJvbSAnLi4vdHlwZXMnO1xuXG4vKipcbiAqIERvd25sb2FkIFVSTCByZXNwb25zZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIERvd25sb2FkVXJsUmVzcG9uc2Uge1xuICBkb3dubG9hZFVybDogc3RyaW5nO1xuICBleHBpcmVzQXQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBTdWJzY3JpcHRpb24gc3RhdGUgZm9yIHJlY29ubmVjdGlvblxuICovXG5pbnRlcmZhY2UgU3Vic2NyaXB0aW9uU3RhdGUge1xuICB3czogV2ViU29ja2V0IHwgbnVsbDtcbiAgc3Vic2NyaXB0aW9uSWQ6IHN0cmluZztcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIG9uRXZlbnQ6IChldmVudDogRXZlbnQpID0+IHZvaWQ7XG4gIG9uRXJyb3I/OiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkO1xuICByZWNvbm5lY3RBdHRlbXB0czogbnVtYmVyO1xuICByZWNvbm5lY3RUaW1lcj86IE5vZGVKUy5UaW1lb3V0O1xuICBpc1JlY29ubmVjdGluZzogYm9vbGVhbjtcbiAga2VlcEFsaXZlVGltZXI/OiBOb2RlSlMuVGltZW91dDtcbn1cblxuLyoqXG4gKiBSZWNvbm5lY3Rpb24gY29uZmlndXJhdGlvbiDigJQgdHdvLXBoYXNlIHN0cmF0ZWd5OlxuICogUGhhc2UgMSAodXJnZW50KTogRXhwb25lbnRpYWwgYmFja29mZiAxcyDihpIgNjBzIGZvciBmaXJzdCAxMCBhdHRlbXB0c1xuICogUGhhc2UgMiAocGVyc2lzdGVudCk6IFJldHJ5IGV2ZXJ5IDUgbWludXRlcyBpbmRlZmluaXRlbHlcbiAqL1xuY29uc3QgUkVDT05ORUNUX0NPTkZJRyA9IHtcbiAgdXJnZW50TWF4QXR0ZW1wdHM6IDEwLFxuICBiYXNlRGVsYXlNczogMTAwMCxcbiAgbWF4RGVsYXlNczogNjAwMDAsXG4gIGJhY2tvZmZNdWx0aXBsaWVyOiAyLFxuICBwZXJzaXN0ZW50RGVsYXlNczogNSAqIDYwICogMTAwMCwgLy8gNSBtaW51dGVzXG59O1xuXG4vKipcbiAqIEFwcFN5bmMgR3JhcGhRTCBjbGllbnQgd2l0aCBXZWJTb2NrZXQgc3Vic2NyaXB0aW9uc1xuICovXG5leHBvcnQgY2xhc3MgQXBwU3luY0NsaWVudCB7XG4gIHByaXZhdGUgYXV0aGVudGljYXRlZDogYm9vbGVhbiA9IGZhbHNlO1xuICBwcml2YXRlIGN1cnJlbnRVc2VySWQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGN1cnJlbnRFbWFpbDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgdG9rZW5zOiBUb2tlbkRhdGEgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBhY3RpdmVTdWJzY3JpcHRpb25zOiBNYXA8c3RyaW5nLCBTdWJzY3JpcHRpb25TdGF0ZT4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgZW52aXJvbm1lbnQ6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICAvLyBHZXQgZW52aXJvbm1lbnQgZnJvbSBjZW50cmFsaXplZCBjb25maWcgKHJlYWRzIHByb2Nlc3MuZW52LkVOVklST05NRU5UKVxuICAgIHRoaXMuZW52aXJvbm1lbnQgPSBnZXRFbnZpcm9ubWVudCgpO1xuICAgIGxvZ2dlci5pbmZvKCdbQXBwU3luY0NsaWVudF0gSW5pdGlhbGl6ZWQnLCB7IGVudmlyb25tZW50OiB0aGlzLmVudmlyb25tZW50IH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY3VycmVudCBhdXRoZW50aWNhdGVkIHVzZXIgSURcbiAgICovXG4gIHB1YmxpYyBnZXRDdXJyZW50VXNlcklkKCk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnRVc2VySWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm90IGF1dGhlbnRpY2F0ZWQuIENhbGwgYXV0aGVudGljYXRlV2l0aFN0b3JlZFRva2VucygpIGZpcnN0LicpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jdXJyZW50VXNlcklkO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY3VycmVudCBhdXRoZW50aWNhdGVkIHVzZXIgZW1haWxcbiAgICovXG4gIHB1YmxpYyBnZXRDdXJyZW50VXNlckVtYWlsKCk6IHN0cmluZyB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRFbWFpbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdXRoZW50aWNhdGUgdXNpbmcgc3RvcmVkIE9BdXRoIHRva2VucyBmcm9tIGtleWNoYWluXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgYXV0aGVudGljYXRlV2l0aFN0b3JlZFRva2VucygpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdG9rZW5zID0gYXdhaXQga2V5Y2hhaW5NYW5hZ2VyLmdldFRva2Vucyh0aGlzLmVudmlyb25tZW50KTtcbiAgICAgIGlmICghdG9rZW5zKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnW0FwcFN5bmNDbGllbnRdIE5vIHN0b3JlZCB0b2tlbnMgZm91bmQnKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBsb2dnZXIuaW5mbygnW0FwcFN5bmNDbGllbnRdIEZvdW5kIHN0b3JlZCBPQXV0aCB0b2tlbnMnLCB7XG4gICAgICAgIHVzZXJJZDogdG9rZW5zLnVzZXJJZCxcbiAgICAgICAgZW1haWw6IHRva2Vucy5lbWFpbCxcbiAgICAgICAgZXhwaXJlZDoga2V5Y2hhaW5NYW5hZ2VyLmlzVG9rZW5FeHBpcmVkKHRva2VucyksXG4gICAgICB9KTtcblxuICAgICAgLy8gSWYgdG9rZW5zIGFyZSBleHBpcmVkLCB0cnkgdG8gcmVmcmVzaCB0aGVtXG4gICAgICBpZiAoa2V5Y2hhaW5NYW5hZ2VyLmlzVG9rZW5FeHBpcmVkKHRva2VucykpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oJ1tBcHBTeW5jQ2xpZW50XSBUb2tlbnMgZXhwaXJlZCwgYXR0ZW1wdGluZyByZWZyZXNoLi4uJyk7XG4gICAgICAgIGNvbnN0IHJlZnJlc2hlZCA9IGF3YWl0IHRoaXMucmVmcmVzaFRva2Vucyh0b2tlbnMpO1xuICAgICAgICBpZiAoIXJlZnJlc2hlZCkge1xuICAgICAgICAgIGxvZ2dlci53YXJuKCdbQXBwU3luY0NsaWVudF0gVG9rZW4gcmVmcmVzaCBmYWlsZWQnKTtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMudG9rZW5zID0gdG9rZW5zO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmN1cnJlbnRVc2VySWQgPSB0aGlzLnRva2VucyEudXNlcklkO1xuICAgICAgdGhpcy5jdXJyZW50RW1haWwgPSB0aGlzLnRva2VucyEuZW1haWw7XG4gICAgICB0aGlzLmF1dGhlbnRpY2F0ZWQgPSB0cnVlO1xuXG4gICAgICBsb2dnZXIuaW5mbygnW0FwcFN5bmNDbGllbnRdIEF1dGhlbnRpY2F0ZWQgc3VjY2Vzc2Z1bGx5Jywge1xuICAgICAgICB1c2VySWQ6IHRoaXMuY3VycmVudFVzZXJJZCxcbiAgICAgICAgZW1haWw6IHRoaXMuY3VycmVudEVtYWlsLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ1tBcHBTeW5jQ2xpZW50XSBBdXRoZW50aWNhdGlvbiBmYWlsZWQ6JywgZXJyb3IpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWZyZXNoIGV4cGlyZWQgdG9rZW5zXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlZnJlc2hUb2tlbnModG9rZW5zOiBUb2tlbkRhdGEpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY29uZmlnID0gZ2V0Q29uZmlnKCk7XG4gICAgICBjb25zdCB0b2tlblVybCA9IGBodHRwczovLyR7Y29uZmlnLmF3cy5jb2duaXRvRG9tYWlufS9vYXV0aDIvdG9rZW5gO1xuXG4gICAgICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcbiAgICAgICAgZ3JhbnRfdHlwZTogJ3JlZnJlc2hfdG9rZW4nLFxuICAgICAgICBjbGllbnRfaWQ6IGNvbmZpZy5hd3MuY29nbml0b0NsaWVudElkLFxuICAgICAgICByZWZyZXNoX3Rva2VuOiB0b2tlbnMucmVmcmVzaFRva2VuLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godG9rZW5VcmwsIHtcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnIH0sXG4gICAgICAgIGJvZHk6IHBhcmFtcy50b1N0cmluZygpLFxuICAgICAgfSk7XG5cbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdbQXBwU3luY0NsaWVudF0gVG9rZW4gcmVmcmVzaCBmYWlsZWQnLCB7IHN0YXR1czogcmVzcG9uc2Uuc3RhdHVzIH0pO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCkgYXMge1xuICAgICAgICBhY2Nlc3NfdG9rZW46IHN0cmluZztcbiAgICAgICAgaWRfdG9rZW46IHN0cmluZztcbiAgICAgICAgZXhwaXJlc19pbjogbnVtYmVyO1xuICAgICAgfTtcblxuICAgICAgY29uc3QgdXBkYXRlZFRva2VuczogVG9rZW5EYXRhID0ge1xuICAgICAgICAuLi50b2tlbnMsXG4gICAgICAgIGFjY2Vzc1Rva2VuOiBkYXRhLmFjY2Vzc190b2tlbixcbiAgICAgICAgaWRUb2tlbjogZGF0YS5pZF90b2tlbixcbiAgICAgICAgZXhwaXJlc0F0OiBEYXRlLm5vdygpICsgKGRhdGEuZXhwaXJlc19pbiAqIDEwMDApLFxuICAgICAgfTtcblxuICAgICAgYXdhaXQga2V5Y2hhaW5NYW5hZ2VyLnNldFRva2Vucyh1cGRhdGVkVG9rZW5zLCB0aGlzLmVudmlyb25tZW50KTtcbiAgICAgIHRoaXMudG9rZW5zID0gdXBkYXRlZFRva2VucztcblxuICAgICAgbG9nZ2VyLmluZm8oJ1tBcHBTeW5jQ2xpZW50XSBUb2tlbnMgcmVmcmVzaGVkJywge1xuICAgICAgICBleHBpcmVzQXQ6IG5ldyBEYXRlKHVwZGF0ZWRUb2tlbnMuZXhwaXJlc0F0KS50b0lTT1N0cmluZygpLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ1tBcHBTeW5jQ2xpZW50XSBUb2tlbiByZWZyZXNoIGVycm9yOicsIGVycm9yKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgYXV0aGVudGljYXRlZFxuICAgKi9cbiAgcHVibGljIGlzQXV0aGVudGljYXRlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5hdXRoZW50aWNhdGVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFNpZ24gb3V0XG4gICAqL1xuICBwdWJsaWMgc2lnbk91dCgpOiB2b2lkIHtcbiAgICB0aGlzLmF1dGhlbnRpY2F0ZWQgPSBmYWxzZTtcbiAgICB0aGlzLnRva2VucyA9IG51bGw7XG4gICAgdGhpcy5jdXJyZW50VXNlcklkID0gbnVsbDtcbiAgICB0aGlzLmN1cnJlbnRFbWFpbCA9IG51bGw7XG4gICAgdGhpcy5jbGVhbnVwU3Vic2NyaXB0aW9ucygpO1xuICAgIGxvZ2dlci5pbmZvKCdbQXBwU3luY0NsaWVudF0gU2lnbmVkIG91dCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ha2UgYSBHcmFwaFFMIHJlcXVlc3RcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZ3JhcGhxbFJlcXVlc3QocXVlcnk6IHN0cmluZywgdmFyaWFibGVzOiBhbnksIGlzUmV0cnk6IGJvb2xlYW4gPSBmYWxzZSk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgY29uZmlnID0gZ2V0Q29uZmlnKCk7XG5cbiAgICBpZiAoIXRoaXMudG9rZW5zPy5pZFRva2VuKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBhdXRoZW50aWNhdGVkLiBSdW4gXCJjb2RldmliZSBsb2dpblwiIGZpcnN0LicpO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgJ0F1dGhvcml6YXRpb24nOiB0aGlzLnRva2Vucy5pZFRva2VuLFxuICAgIH07XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGNvbmZpZy5hd3MuYXBwc3luY1VybCwge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBoZWFkZXJzLFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBxdWVyeSwgdmFyaWFibGVzIH0pLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcmVzcG9uc2UuanNvbigpIGFzIHsgZGF0YT86IGFueTsgZXJyb3JzPzogQXJyYXk8eyBtZXNzYWdlOiBzdHJpbmcgfT4gfTtcblxuICAgIC8vIEhhbmRsZSA0MDEgd2l0aCB0b2tlbiByZWZyZXNoXG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gNDAxICYmICFpc1JldHJ5ICYmIHRoaXMudG9rZW5zKSB7XG4gICAgICBsb2dnZXIuaW5mbygnW0FwcFN5bmNDbGllbnRdIDQwMSBVbmF1dGhvcml6ZWQsIHJlZnJlc2hpbmcgdG9rZW4uLi4nKTtcbiAgICAgIGNvbnN0IHJlZnJlc2hlZCA9IGF3YWl0IHRoaXMucmVmcmVzaFRva2Vucyh0aGlzLnRva2Vucyk7XG4gICAgICBpZiAocmVmcmVzaGVkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyYXBocWxSZXF1ZXN0KHF1ZXJ5LCB2YXJpYWJsZXMsIHRydWUpO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUb2tlbiBleHBpcmVkIGFuZCByZWZyZXNoIGZhaWxlZCcpO1xuICAgIH1cblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgR3JhcGhRTCByZXF1ZXN0IGZhaWxlZDogJHtyZXNwb25zZS5zdGF0dXN9YCk7XG4gICAgfVxuXG4gICAgaWYgKHJlc3VsdC5lcnJvcnM/Lmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBHcmFwaFFMIGVycm9yOiAke3Jlc3VsdC5lcnJvcnNbMF0ubWVzc2FnZX1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLy8gTUFSSzogLSBTZXNzaW9uIE9wZXJhdGlvbnNcblxuICAvKipcbiAgICogQ3JlYXRlIGEgc2Vzc2lvblxuICAgKi9cbiAgcHVibGljIGFzeW5jIGNyZWF0ZVNlc3Npb24oaW5wdXQ6IENyZWF0ZVNlc3Npb25JbnB1dCk6IFByb21pc2U8U2Vzc2lvbj4ge1xuICAgIGNvbnN0IHByZXBhcmVkSW5wdXQgPSB7XG4gICAgICAuLi5pbnB1dCxcbiAgICAgIG1ldGFkYXRhOiBpbnB1dC5tZXRhZGF0YSA/IEpTT04uc3RyaW5naWZ5KGlucHV0Lm1ldGFkYXRhKSA6IHVuZGVmaW5lZCxcbiAgICB9O1xuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdyYXBocWxSZXF1ZXN0KG11dGF0aW9ucy5jcmVhdGVTZXNzaW9uLCB7IGlucHV0OiBwcmVwYXJlZElucHV0IH0pO1xuICAgIGxvZ2dlci5pbmZvKCdbQXBwU3luY0NsaWVudF0gU2Vzc2lvbiBjcmVhdGVkJywgeyBzZXNzaW9uSWQ6IHJlc3BvbnNlLmRhdGEuY3JlYXRlU2Vzc2lvbi5zZXNzaW9uSWQgfSk7XG4gICAgcmV0dXJuIHJlc3BvbnNlLmRhdGEuY3JlYXRlU2Vzc2lvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgYSBzZXNzaW9uXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdXBkYXRlU2Vzc2lvbihpbnB1dDogVXBkYXRlU2Vzc2lvbklucHV0KTogUHJvbWlzZTxTZXNzaW9uPiB7XG4gICAgY29uc3QgcHJlcGFyZWRJbnB1dCA9IHtcbiAgICAgIC4uLmlucHV0LFxuICAgICAgbWV0YWRhdGE6IGlucHV0Lm1ldGFkYXRhID8gSlNPTi5zdHJpbmdpZnkoaW5wdXQubWV0YWRhdGEpIDogdW5kZWZpbmVkLFxuICAgIH07XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ3JhcGhxbFJlcXVlc3QobXV0YXRpb25zLnVwZGF0ZVNlc3Npb24sIHsgaW5wdXQ6IHByZXBhcmVkSW5wdXQgfSk7XG4gICAgbG9nZ2VyLmRlYnVnKCdbQXBwU3luY0NsaWVudF0gU2Vzc2lvbiB1cGRhdGVkJywgeyBzZXNzaW9uSWQ6IHJlc3BvbnNlLmRhdGEudXBkYXRlU2Vzc2lvbi5zZXNzaW9uSWQgfSk7XG4gICAgcmV0dXJuIHJlc3BvbnNlLmRhdGEudXBkYXRlU2Vzc2lvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYSBzZXNzaW9uXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZ2V0U2Vzc2lvbihzZXNzaW9uSWQ6IHN0cmluZyk6IFByb21pc2U8U2Vzc2lvbiB8IG51bGw+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ3JhcGhxbFJlcXVlc3QocXVlcmllcy5nZXRTZXNzaW9uLCB7IHNlc3Npb25JZCB9KTtcbiAgICByZXR1cm4gcmVzcG9uc2UuZGF0YS5nZXRTZXNzaW9uO1xuICB9XG5cbiAgLy8gTUFSSzogLSBFdmVudCBPcGVyYXRpb25zXG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhbiBldmVudFxuICAgKi9cbiAgcHVibGljIGFzeW5jIGNyZWF0ZUV2ZW50KGlucHV0OiBDcmVhdGVFdmVudElucHV0KTogUHJvbWlzZTxFdmVudD4ge1xuICAgIGNvbnN0IHByZXBhcmVkSW5wdXQgPSB7XG4gICAgICAuLi5pbnB1dCxcbiAgICAgIG1ldGFkYXRhOiBpbnB1dC5tZXRhZGF0YSA/IEpTT04uc3RyaW5naWZ5KGlucHV0Lm1ldGFkYXRhKSA6IHVuZGVmaW5lZCxcbiAgICB9O1xuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdyYXBocWxSZXF1ZXN0KG11dGF0aW9ucy5jcmVhdGVFdmVudCwgeyBpbnB1dDogcHJlcGFyZWRJbnB1dCB9KTtcbiAgICBsb2dnZXIuZGVidWcoJ1tBcHBTeW5jQ2xpZW50XSBFdmVudCBjcmVhdGVkJywge1xuICAgICAgZXZlbnRJZDogcmVzcG9uc2UuZGF0YS5jcmVhdGVFdmVudC5ldmVudElkLFxuICAgICAgdHlwZTogcmVzcG9uc2UuZGF0YS5jcmVhdGVFdmVudC50eXBlLFxuICAgIH0pO1xuICAgIHJldHVybiByZXNwb25zZS5kYXRhLmNyZWF0ZUV2ZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSBldmVudCBzdGF0dXNcbiAgICovXG4gIHB1YmxpYyBhc3luYyB1cGRhdGVFdmVudFN0YXR1cyhpbnB1dDogVXBkYXRlRXZlbnRTdGF0dXNJbnB1dCk6IFByb21pc2U8RXZlbnQ+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ3JhcGhxbFJlcXVlc3QobXV0YXRpb25zLnVwZGF0ZUV2ZW50U3RhdHVzLCB7IGlucHV0IH0pO1xuICAgIHJldHVybiByZXNwb25zZS5kYXRhLnVwZGF0ZUV2ZW50U3RhdHVzO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3QgZXZlbnRzIGZvciBhIHNlc3Npb25cbiAgICovXG4gIHB1YmxpYyBhc3luYyBsaXN0RXZlbnRzKHNlc3Npb25JZDogc3RyaW5nLCBzb3VyY2U/OiBFdmVudFNvdXJjZSwgbGltaXQ/OiBudW1iZXIpOiBQcm9taXNlPEV2ZW50W10+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ3JhcGhxbFJlcXVlc3QocXVlcmllcy5saXN0RXZlbnRzLCB7IHNlc3Npb25JZCwgc291cmNlLCBsaW1pdCB9KTtcbiAgICByZXR1cm4gcmVzcG9uc2UuZGF0YS5saXN0RXZlbnRzLml0ZW1zO1xuICB9XG5cbiAgLy8gTUFSSzogLSBEZXZpY2UgS2V5IE9wZXJhdGlvbnNcblxuICAvKipcbiAgICogTGlzdCB1c2VyIGRldmljZSBrZXlzXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgbGlzdFVzZXJEZXZpY2VLZXlzKCk6IFByb21pc2U8RGV2aWNlS2V5W10+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ3JhcGhxbFJlcXVlc3QocXVlcmllcy5saXN0VXNlckRldmljZUtleXMsIHt9KTtcbiAgICByZXR1cm4gcmVzcG9uc2UuZGF0YS5saXN0VXNlckRldmljZUtleXMgfHwgW107XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgZGV2aWNlIGtleVxuICAgKi9cbiAgcHVibGljIGFzeW5jIHJlZ2lzdGVyRGV2aWNlS2V5KFxuICAgIGRldmljZUlkOiBzdHJpbmcsXG4gICAgcHVibGljS2V5OiBzdHJpbmcsXG4gICAgcGxhdGZvcm06IHN0cmluZyxcbiAgICBkZXZpY2VOYW1lOiBzdHJpbmdcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgaW5wdXQgPSB7IGRldmljZUlkLCBwdWJsaWNLZXksIHBsYXRmb3JtLCBkZXZpY2VOYW1lIH07XG4gICAgYXdhaXQgdGhpcy5ncmFwaHFsUmVxdWVzdChtdXRhdGlvbnMucmVnaXN0ZXJEZXZpY2VLZXksIHsgaW5wdXQgfSk7XG4gICAgbG9nZ2VyLmluZm8oJ1tBcHBTeW5jQ2xpZW50XSBEZXZpY2Uga2V5IHJlZ2lzdGVyZWQnLCB7IGRldmljZUlkLCBwbGF0Zm9ybSB9KTtcbiAgfVxuXG4gIC8vIE1BUks6IC0gQXR0YWNobWVudCBPcGVyYXRpb25zXG5cbiAgLyoqXG4gICAqIEdldCBhdHRhY2htZW50IGRvd25sb2FkIFVSTFxuICAgKi9cbiAgcHVibGljIGFzeW5jIGdldEF0dGFjaG1lbnREb3dubG9hZFVybChzM0tleTogc3RyaW5nKTogUHJvbWlzZTxEb3dubG9hZFVybFJlc3BvbnNlPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdyYXBocWxSZXF1ZXN0KG11dGF0aW9ucy5nZXRBdHRhY2htZW50RG93bmxvYWRVcmwsIHsgczNLZXkgfSk7XG4gICAgcmV0dXJuIHJlc3BvbnNlLmRhdGEuZ2V0QXR0YWNobWVudERvd25sb2FkVXJsO1xuICB9XG5cbiAgLy8gTUFSSzogLSBTdWJzY3JpcHRpb25zXG5cbiAgLyoqXG4gICAqIFN1YnNjcmliZSB0byBldmVudHMgZm9yIGEgc2Vzc2lvblxuICAgKi9cbiAgcHVibGljIHN1YnNjcmliZVRvRXZlbnRzKFxuICAgIHNlc3Npb25JZDogc3RyaW5nLFxuICAgIG9uRXZlbnQ6IChldmVudDogRXZlbnQpID0+IHZvaWQsXG4gICAgb25FcnJvcj86IChlcnJvcjogRXJyb3IpID0+IHZvaWRcbiAgKTogKCkgPT4gdm9pZCB7XG4gICAgbG9nZ2VyLmluZm8oJ1tBcHBTeW5jQ2xpZW50XSBTdWJzY3JpYmluZyB0byBldmVudHMnLCB7IHNlc3Npb25JZCB9KTtcblxuICAgIC8vIENsZWFudXAgZXhpc3Rpbmcgc3Vic2NyaXB0aW9uXG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLmFjdGl2ZVN1YnNjcmlwdGlvbnMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICB0aGlzLmNsZWFudXBTdWJzY3JpcHRpb25TdGF0ZShleGlzdGluZyk7XG4gICAgICB0aGlzLmFjdGl2ZVN1YnNjcmlwdGlvbnMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgfVxuXG4gICAgY29uc3Qgc3RhdGU6IFN1YnNjcmlwdGlvblN0YXRlID0ge1xuICAgICAgd3M6IG51bGwsXG4gICAgICBzdWJzY3JpcHRpb25JZDogdXVpZHY0KCksXG4gICAgICBzZXNzaW9uSWQsXG4gICAgICBvbkV2ZW50LFxuICAgICAgb25FcnJvcixcbiAgICAgIHJlY29ubmVjdEF0dGVtcHRzOiAwLFxuICAgICAgaXNSZWNvbm5lY3Rpbmc6IGZhbHNlLFxuICAgIH07XG5cbiAgICB0aGlzLmFjdGl2ZVN1YnNjcmlwdGlvbnMuc2V0KHNlc3Npb25JZCwgc3RhdGUpO1xuICAgIHRoaXMuY3JlYXRlU3Vic2NyaXB0aW9uKHN0YXRlKTtcblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICB0aGlzLmNsZWFudXBTdWJzY3JpcHRpb25TdGF0ZShzdGF0ZSk7XG4gICAgICB0aGlzLmFjdGl2ZVN1YnNjcmlwdGlvbnMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBXZWJTb2NrZXQgVVJMXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkUmVhbHRpbWVVcmwoKTogc3RyaW5nIHtcbiAgICBjb25zdCBjb25maWcgPSBnZXRDb25maWcoKTtcbiAgICBjb25zdCByZWFsdGltZVVybCA9IGNvbmZpZy5hd3MuYXBwc3luY1VybFxuICAgICAgLnJlcGxhY2UoJ2h0dHBzOi8vJywgJ3dzczovLycpXG4gICAgICAucmVwbGFjZSgnYXBwc3luYy1hcGknLCAnYXBwc3luYy1yZWFsdGltZS1hcGknKTtcblxuICAgIGNvbnN0IGF1dGhIZWFkZXI6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICBob3N0OiBuZXcgVVJMKGNvbmZpZy5hd3MuYXBwc3luY1VybCkuaG9zdCxcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMudG9rZW5zPy5pZFRva2VuKSB7XG4gICAgICBhdXRoSGVhZGVyWydBdXRob3JpemF0aW9uJ10gPSB0aGlzLnRva2Vucy5pZFRva2VuO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWRlckJhc2U2NCA9IEJ1ZmZlci5mcm9tKEpTT04uc3RyaW5naWZ5KGF1dGhIZWFkZXIpKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgY29uc3QgcGF5bG9hZEJhc2U2NCA9IEJ1ZmZlci5mcm9tKEpTT04uc3RyaW5naWZ5KHt9KSkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuXG4gICAgcmV0dXJuIGAke3JlYWx0aW1lVXJsfT9oZWFkZXI9JHtoZWFkZXJCYXNlNjR9JnBheWxvYWQ9JHtwYXlsb2FkQmFzZTY0fWA7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIFdlYlNvY2tldCBzdWJzY3JpcHRpb25cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlU3Vic2NyaXB0aW9uKHN0YXRlOiBTdWJzY3JpcHRpb25TdGF0ZSk6IHZvaWQge1xuICAgIGNvbnN0IHsgc2Vzc2lvbklkLCBzdWJzY3JpcHRpb25JZCwgb25FdmVudCwgb25FcnJvciB9ID0gc3RhdGU7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgd3NVcmwgPSB0aGlzLmJ1aWxkUmVhbHRpbWVVcmwoKTtcbiAgICAgIGNvbnN0IHdzID0gbmV3IFdlYlNvY2tldCh3c1VybCwgWydncmFwaHFsLXdzJ10pO1xuXG4gICAgICB3cy5vbignb3BlbicsICgpID0+IHtcbiAgICAgICAgbG9nZ2VyLmluZm8oJ1tBcHBTeW5jQ2xpZW50XSBXZWJTb2NrZXQgY29ubmVjdGVkJywgeyBzZXNzaW9uSWQgfSk7XG4gICAgICAgIHdzLnNlbmQoSlNPTi5zdHJpbmdpZnkoeyB0eXBlOiAnY29ubmVjdGlvbl9pbml0JyB9KSk7XG4gICAgICB9KTtcblxuICAgICAgd3Mub24oJ21lc3NhZ2UnLCAoZGF0YTogV2ViU29ja2V0LkRhdGEpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBtZXNzYWdlID0gSlNPTi5wYXJzZShkYXRhLnRvU3RyaW5nKCkpO1xuXG4gICAgICAgICAgc3dpdGNoIChtZXNzYWdlLnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2Nvbm5lY3Rpb25fYWNrJzpcbiAgICAgICAgICAgICAgdGhpcy5zZW5kU3Vic2NyaXB0aW9uU3RhcnQod3MsIHN0YXRlKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ3N0YXJ0X2Fjayc6XG4gICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdbQXBwU3luY0NsaWVudF0gU3Vic2NyaXB0aW9uIHN0YXJ0ZWQnLCB7IHNlc3Npb25JZCB9KTtcbiAgICAgICAgICAgICAgc3RhdGUuaXNSZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgc3RhdGUucmVjb25uZWN0QXR0ZW1wdHMgPSAwO1xuICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSAnZGF0YSc6XG4gICAgICAgICAgICAgIHRoaXMucmVzZXRLZWVwQWxpdmVUaW1lcihzdGF0ZSk7XG4gICAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0gbWVzc2FnZS5wYXlsb2FkPy5kYXRhPy5vbkV2ZW50Q3JlYXRlZDtcbiAgICAgICAgICAgICAgaWYgKGV2ZW50ICYmIGV2ZW50LnNvdXJjZSA9PT0gRXZlbnRTb3VyY2UuTU9CSUxFKSB7XG4gICAgICAgICAgICAgICAgb25FdmVudChldmVudCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ2thJzpcbiAgICAgICAgICAgICAgdGhpcy5yZXNldEtlZXBBbGl2ZVRpbWVyKHN0YXRlKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ2Vycm9yJzpcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3JNc2cgPSBtZXNzYWdlLnBheWxvYWQ/LmVycm9ycz8uWzBdPy5tZXNzYWdlIHx8ICdVbmtub3duIGVycm9yJztcbiAgICAgICAgICAgICAgdGhpcy5oYW5kbGVTdWJzY3JpcHRpb25FcnJvcihzdGF0ZSwgbmV3IEVycm9yKGVycm9yTXNnKSk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcignW0FwcFN5bmNDbGllbnRdIEZhaWxlZCB0byBwYXJzZSBtZXNzYWdlJywgeyBlcnJvcjogZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHdzLm9uKCdlcnJvcicsIChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdbQXBwU3luY0NsaWVudF0gV2ViU29ja2V0IGVycm9yJywgeyBzZXNzaW9uSWQsIGVycm9yOiBlcnJvci5tZXNzYWdlIH0pO1xuICAgICAgICB0aGlzLmhhbmRsZVN1YnNjcmlwdGlvbkVycm9yKHN0YXRlLCBlcnJvcik7XG4gICAgICB9KTtcblxuICAgICAgd3Mub24oJ2Nsb3NlJywgKGNvZGU6IG51bWJlciwgcmVhc29uOiBCdWZmZXIpID0+IHtcbiAgICAgICAgbG9nZ2VyLmluZm8oJ1tBcHBTeW5jQ2xpZW50XSBXZWJTb2NrZXQgY2xvc2VkJywgeyBzZXNzaW9uSWQsIGNvZGUgfSk7XG4gICAgICAgIGlmIChzdGF0ZS5rZWVwQWxpdmVUaW1lcikge1xuICAgICAgICAgIGNsZWFyVGltZW91dChzdGF0ZS5rZWVwQWxpdmVUaW1lcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvZGUgIT09IDEwMDAgJiYgdGhpcy5hY3RpdmVTdWJzY3JpcHRpb25zLmhhcyhzZXNzaW9uSWQpKSB7XG4gICAgICAgICAgdGhpcy5oYW5kbGVTdWJzY3JpcHRpb25FcnJvcihzdGF0ZSwgbmV3IEVycm9yKGBXZWJTb2NrZXQgY2xvc2VkOiAke2NvZGV9YCkpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgc3RhdGUud3MgPSB3cztcbiAgICAgIHRoaXMucmVzZXRLZWVwQWxpdmVUaW1lcihzdGF0ZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMuaGFuZGxlU3Vic2NyaXB0aW9uRXJyb3Ioc3RhdGUsIGVycm9yIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2VuZCBzdWJzY3JpcHRpb24gc3RhcnQgbWVzc2FnZVxuICAgKi9cbiAgcHJpdmF0ZSBzZW5kU3Vic2NyaXB0aW9uU3RhcnQod3M6IFdlYlNvY2tldCwgc3RhdGU6IFN1YnNjcmlwdGlvblN0YXRlKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0gZ2V0Q29uZmlnKCk7XG4gICAgY29uc3QgeyBzZXNzaW9uSWQsIHN1YnNjcmlwdGlvbklkIH0gPSBzdGF0ZTtcblxuICAgIGNvbnN0IGF1dGhIZWFkZXI6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICBob3N0OiBuZXcgVVJMKGNvbmZpZy5hd3MuYXBwc3luY1VybCkuaG9zdCxcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMudG9rZW5zPy5pZFRva2VuKSB7XG4gICAgICBhdXRoSGVhZGVyWydBdXRob3JpemF0aW9uJ10gPSB0aGlzLnRva2Vucy5pZFRva2VuO1xuICAgIH1cblxuICAgIHdzLnNlbmQoSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgaWQ6IHN1YnNjcmlwdGlvbklkLFxuICAgICAgdHlwZTogJ3N0YXJ0JyxcbiAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgZGF0YTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgIHF1ZXJ5OiBzdWJzY3JpcHRpb25zLm9uRXZlbnRDcmVhdGVkLFxuICAgICAgICAgIHZhcmlhYmxlczogeyBzZXNzaW9uSWQgfSxcbiAgICAgICAgfSksXG4gICAgICAgIGV4dGVuc2lvbnM6IHsgYXV0aG9yaXphdGlvbjogYXV0aEhlYWRlciB9LFxuICAgICAgfSxcbiAgICB9KSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQga2VlcC1hbGl2ZSB0aW1lclxuICAgKi9cbiAgcHJpdmF0ZSByZXNldEtlZXBBbGl2ZVRpbWVyKHN0YXRlOiBTdWJzY3JpcHRpb25TdGF0ZSk6IHZvaWQge1xuICAgIGlmIChzdGF0ZS5rZWVwQWxpdmVUaW1lcikge1xuICAgICAgY2xlYXJUaW1lb3V0KHN0YXRlLmtlZXBBbGl2ZVRpbWVyKTtcbiAgICB9XG4gICAgc3RhdGUua2VlcEFsaXZlVGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuaGFuZGxlU3Vic2NyaXB0aW9uRXJyb3Ioc3RhdGUsIG5ldyBFcnJvcignS2VlcC1hbGl2ZSB0aW1lb3V0JykpO1xuICAgIH0sIDUgKiA2MCAqIDEwMDApO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSBzdWJzY3JpcHRpb24gZXJyb3Igd2l0aCB0d28tcGhhc2UgcmVjb25uZWN0aW9uOlxuICAgKiBQaGFzZSAxICh1cmdlbnQpOiBFeHBvbmVudGlhbCBiYWNrb2ZmIGZvciBmaXJzdCBOIGF0dGVtcHRzXG4gICAqIFBoYXNlIDIgKHBlcnNpc3RlbnQpOiBGaXhlZCBpbnRlcnZhbCByZXRyeSBpbmRlZmluaXRlbHlcbiAgICovXG4gIHByaXZhdGUgaGFuZGxlU3Vic2NyaXB0aW9uRXJyb3Ioc3RhdGU6IFN1YnNjcmlwdGlvblN0YXRlLCBlcnJvcjogRXJyb3IpOiB2b2lkIHtcbiAgICBjb25zdCB7IHNlc3Npb25JZCwgb25FcnJvciB9ID0gc3RhdGU7XG5cbiAgICBpZiAoc3RhdGUuaXNSZWNvbm5lY3RpbmcgfHwgIXRoaXMuYWN0aXZlU3Vic2NyaXB0aW9ucy5oYXMoc2Vzc2lvbklkKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHN0YXRlLmlzUmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICBzdGF0ZS5yZWNvbm5lY3RBdHRlbXB0cysrO1xuXG4gICAgY29uc3QgaXNVcmdlbnRQaGFzZSA9IHN0YXRlLnJlY29ubmVjdEF0dGVtcHRzIDw9IFJFQ09OTkVDVF9DT05GSUcudXJnZW50TWF4QXR0ZW1wdHM7XG5cbiAgICBsZXQgZGVsYXk6IG51bWJlcjtcbiAgICBpZiAoaXNVcmdlbnRQaGFzZSkge1xuICAgICAgZGVsYXkgPSBNYXRoLm1pbihcbiAgICAgICAgUkVDT05ORUNUX0NPTkZJRy5iYXNlRGVsYXlNcyAqIE1hdGgucG93KFJFQ09OTkVDVF9DT05GSUcuYmFja29mZk11bHRpcGxpZXIsIHN0YXRlLnJlY29ubmVjdEF0dGVtcHRzIC0gMSksXG4gICAgICAgIFJFQ09OTkVDVF9DT05GSUcubWF4RGVsYXlNc1xuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVsYXkgPSBSRUNPTk5FQ1RfQ09ORklHLnBlcnNpc3RlbnREZWxheU1zO1xuICAgICAgaWYgKHN0YXRlLnJlY29ubmVjdEF0dGVtcHRzID09PSBSRUNPTk5FQ1RfQ09ORklHLnVyZ2VudE1heEF0dGVtcHRzICsgMSkge1xuICAgICAgICBsb2dnZXIuaW5mbygnW0FwcFN5bmNDbGllbnRdIFN3aXRjaGluZyB0byBwZXJzaXN0ZW50IHJlY29ubmVjdCAoZXZlcnkgNW1pbiknLCB7IHNlc3Npb25JZCB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsb2dnZXIuaW5mbygnW0FwcFN5bmNDbGllbnRdIFNjaGVkdWxpbmcgcmVjb25uZWN0Jywge1xuICAgICAgc2Vzc2lvbklkLFxuICAgICAgYXR0ZW1wdDogc3RhdGUucmVjb25uZWN0QXR0ZW1wdHMsXG4gICAgICBwaGFzZTogaXNVcmdlbnRQaGFzZSA/ICd1cmdlbnQnIDogJ3BlcnNpc3RlbnQnLFxuICAgICAgZGVsYXlNczogZGVsYXksXG4gICAgfSk7XG5cbiAgICBpZiAoc3RhdGUud3MpIHtcbiAgICAgIHRyeSB7IHN0YXRlLndzLmNsb3NlKDEwMDApOyB9IGNhdGNoIChlKSB7IC8qIGlnbm9yZSAqLyB9XG4gICAgICBzdGF0ZS53cyA9IG51bGw7XG4gICAgfVxuXG4gICAgaWYgKHN0YXRlLmtlZXBBbGl2ZVRpbWVyKSB7XG4gICAgICBjbGVhclRpbWVvdXQoc3RhdGUua2VlcEFsaXZlVGltZXIpO1xuICAgIH1cblxuICAgIHN0YXRlLnJlY29ubmVjdFRpbWVyID0gc2V0VGltZW91dChhc3luYyAoKSA9PiB7XG4gICAgICAvLyBSZXNldCBmbGFnIHNvIG5leHQgZmFpbHVyZSBjYW4gdHJpZ2dlciBhbm90aGVyIHJlY29ubmVjdFxuICAgICAgc3RhdGUuaXNSZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgICAgaWYgKCF0aGlzLmFjdGl2ZVN1YnNjcmlwdGlvbnMuaGFzKHNlc3Npb25JZCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBSZWZyZXNoIHRva2VucyBiZWZvcmUgcmVjb25uZWN0aW5nIOKAlCB0aGV5IG1heSBoYXZlIGV4cGlyZWRcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGZyZXNoVG9rZW5zID0gYXdhaXQga2V5Y2hhaW5NYW5hZ2VyLmdldFRva2Vucyh0aGlzLmVudmlyb25tZW50KTtcbiAgICAgICAgaWYgKGZyZXNoVG9rZW5zKSB7XG4gICAgICAgICAgaWYgKGtleWNoYWluTWFuYWdlci5pc1Rva2VuRXhwaXJlZChmcmVzaFRva2VucykpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlZnJlc2hlZCA9IGF3YWl0IHRoaXMucmVmcmVzaFRva2VucyhmcmVzaFRva2Vucyk7XG4gICAgICAgICAgICBpZiAocmVmcmVzaGVkKSB7XG4gICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdbQXBwU3luY0NsaWVudF0gVG9rZW5zIHJlZnJlc2hlZCBiZWZvcmUgcmVjb25uZWN0JywgeyBzZXNzaW9uSWQgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMudG9rZW5zID0gZnJlc2hUb2tlbnM7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdbQXBwU3luY0NsaWVudF0gVG9rZW4gcmVmcmVzaCBmYWlsZWQgYmVmb3JlIHJlY29ubmVjdCwgdXNpbmcgZXhpc3RpbmcgdG9rZW5zJywgeyBzZXNzaW9uSWQgfSk7XG4gICAgICB9XG5cbiAgICAgIHN0YXRlLnN1YnNjcmlwdGlvbklkID0gdXVpZHY0KCk7XG4gICAgICB0aGlzLmNyZWF0ZVN1YnNjcmlwdGlvbihzdGF0ZSk7XG4gICAgfSwgZGVsYXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsZWFudXAgc3Vic2NyaXB0aW9uIHN0YXRlXG4gICAqL1xuICBwcml2YXRlIGNsZWFudXBTdWJzY3JpcHRpb25TdGF0ZShzdGF0ZTogU3Vic2NyaXB0aW9uU3RhdGUpOiB2b2lkIHtcbiAgICBpZiAoc3RhdGUucmVjb25uZWN0VGltZXIpIHtcbiAgICAgIGNsZWFyVGltZW91dChzdGF0ZS5yZWNvbm5lY3RUaW1lcik7XG4gICAgfVxuICAgIGlmIChzdGF0ZS5rZWVwQWxpdmVUaW1lcikge1xuICAgICAgY2xlYXJUaW1lb3V0KHN0YXRlLmtlZXBBbGl2ZVRpbWVyKTtcbiAgICB9XG4gICAgaWYgKHN0YXRlLndzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoc3RhdGUud3MucmVhZHlTdGF0ZSA9PT0gV2ViU29ja2V0Lk9QRU4pIHtcbiAgICAgICAgICBzdGF0ZS53cy5zZW5kKEpTT04uc3RyaW5naWZ5KHsgaWQ6IHN0YXRlLnN1YnNjcmlwdGlvbklkLCB0eXBlOiAnc3RvcCcgfSkpO1xuICAgICAgICAgIHN0YXRlLndzLmNsb3NlKDEwMDApO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlKSB7IC8qIGlnbm9yZSAqLyB9XG4gICAgICBzdGF0ZS53cyA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgLy8gTUFSSzogLSBIZWFydGJlYXRcblxuICBwcml2YXRlIGhlYXJ0YmVhdFRpbWVyczogTWFwPHN0cmluZywgTm9kZUpTLlRpbWVvdXQ+ID0gbmV3IE1hcCgpO1xuXG4gIC8qKlxuICAgKiBTdGFydCBwZXJpb2RpYyBoZWFydGJlYXQgZm9yIGEgc2Vzc2lvbi5cbiAgICogVXBkYXRlcyBsYXN0SGVhcnRiZWF0QXQgb24gdGhlIHNlc3Npb24gZXZlcnkgaW50ZXJ2YWxNcyAoZGVmYXVsdCAyIG1pbnV0ZXMpLlxuICAgKi9cbiAgcHVibGljIHN0YXJ0SGVhcnRiZWF0KHNlc3Npb25JZDogc3RyaW5nLCBpbnRlcnZhbE1zOiBudW1iZXIgPSAyICogNjAgKiAxMDAwKTogdm9pZCB7XG4gICAgdGhpcy5zdG9wSGVhcnRiZWF0KHNlc3Npb25JZCk7XG5cbiAgICAvLyBTZW5kIGluaXRpYWwgaGVhcnRiZWF0IGltbWVkaWF0ZWx5XG4gICAgdGhpcy5zZW5kSGVhcnRiZWF0KHNlc3Npb25JZCk7XG5cbiAgICBjb25zdCB0aW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHRoaXMuc2VuZEhlYXJ0YmVhdChzZXNzaW9uSWQpO1xuICAgIH0sIGludGVydmFsTXMpO1xuXG4gICAgdGhpcy5oZWFydGJlYXRUaW1lcnMuc2V0KHNlc3Npb25JZCwgdGltZXIpO1xuICAgIGxvZ2dlci5pbmZvKCdbQXBwU3luY0NsaWVudF0gSGVhcnRiZWF0IHN0YXJ0ZWQnLCB7IHNlc3Npb25JZCwgaW50ZXJ2YWxNcyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdG9wIGhlYXJ0YmVhdCBmb3IgYSBzZXNzaW9uLlxuICAgKi9cbiAgcHVibGljIHN0b3BIZWFydGJlYXQoc2Vzc2lvbklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCB0aW1lciA9IHRoaXMuaGVhcnRiZWF0VGltZXJzLmdldChzZXNzaW9uSWQpO1xuICAgIGlmICh0aW1lcikge1xuICAgICAgY2xlYXJJbnRlcnZhbCh0aW1lcik7XG4gICAgICB0aGlzLmhlYXJ0YmVhdFRpbWVycy5kZWxldGUoc2Vzc2lvbklkKTtcbiAgICAgIGxvZ2dlci5pbmZvKCdbQXBwU3luY0NsaWVudF0gSGVhcnRiZWF0IHN0b3BwZWQnLCB7IHNlc3Npb25JZCB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2VuZCBhIHNpbmdsZSBoZWFydGJlYXQgdXBkYXRlLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBzZW5kSGVhcnRiZWF0KHNlc3Npb25JZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMudXBkYXRlU2Vzc2lvbih7XG4gICAgICAgIHNlc3Npb25JZCxcbiAgICAgICAgbGFzdEhlYXJ0YmVhdEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICB9KTtcbiAgICAgIGxvZ2dlci5kZWJ1ZygnW0FwcFN5bmNDbGllbnRdIEhlYXJ0YmVhdCBzZW50JywgeyBzZXNzaW9uSWQgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKCdbQXBwU3luY0NsaWVudF0gSGVhcnRiZWF0IGZhaWxlZCcsIHsgc2Vzc2lvbklkLCBlcnJvciB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2xlYW51cCBhbGwgc3Vic2NyaXB0aW9ucyBhbmQgaGVhcnRiZWF0c1xuICAgKi9cbiAgcHVibGljIGNsZWFudXBTdWJzY3JpcHRpb25zKCk6IHZvaWQge1xuICAgIHRoaXMuYWN0aXZlU3Vic2NyaXB0aW9ucy5mb3JFYWNoKChzdGF0ZSkgPT4ge1xuICAgICAgdGhpcy5jbGVhbnVwU3Vic2NyaXB0aW9uU3RhdGUoc3RhdGUpO1xuICAgIH0pO1xuICAgIHRoaXMuYWN0aXZlU3Vic2NyaXB0aW9ucy5jbGVhcigpO1xuXG4gICAgdGhpcy5oZWFydGJlYXRUaW1lcnMuZm9yRWFjaCgodGltZXIpID0+IGNsZWFySW50ZXJ2YWwodGltZXIpKTtcbiAgICB0aGlzLmhlYXJ0YmVhdFRpbWVycy5jbGVhcigpO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,2 @@
1
+ export { AppSyncClient, DownloadUrlResponse } from './appsync-client';
2
+ export { queries, mutations, subscriptions } from './queries';