dbctx 2.0.1 → 2.1.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 (220) hide show
  1. package/dist/index.mjs +6004 -279
  2. package/package.json +11 -8
  3. package/dist/app/assemble.d.mts +0 -5
  4. package/dist/app/assemble.d.mts.map +0 -1
  5. package/dist/app/assemble.mjs +0 -182
  6. package/dist/app/config.d.mts +0 -9
  7. package/dist/app/config.d.mts.map +0 -1
  8. package/dist/app/config.mjs +0 -49
  9. package/dist/app/db.d.mts +0 -9
  10. package/dist/app/db.d.mts.map +0 -1
  11. package/dist/app/db.mjs +0 -182
  12. package/dist/app/detect.d.mts +0 -14
  13. package/dist/app/detect.d.mts.map +0 -1
  14. package/dist/app/detect.mjs +0 -108
  15. package/dist/app/list.d.mts +0 -4
  16. package/dist/app/list.d.mts.map +0 -1
  17. package/dist/app/list.mjs +0 -93
  18. package/dist/app/load-introspection.d.mts +0 -26
  19. package/dist/app/load-introspection.d.mts.map +0 -1
  20. package/dist/app/load-introspection.mjs +0 -89
  21. package/dist/app/login.d.mts +0 -2
  22. package/dist/app/login.d.mts.map +0 -1
  23. package/dist/app/login.mjs +0 -69
  24. package/dist/app/open-url.d.mts +0 -6
  25. package/dist/app/open-url.d.mts.map +0 -1
  26. package/dist/app/open-url.mjs +0 -33
  27. package/dist/app/sample.d.mts +0 -24
  28. package/dist/app/sample.d.mts.map +0 -1
  29. package/dist/app/sample.mjs +0 -257
  30. package/dist/app/session.d.mts +0 -9
  31. package/dist/app/session.d.mts.map +0 -1
  32. package/dist/app/session.mjs +0 -195
  33. package/dist/app/ssh.d.mts +0 -3
  34. package/dist/app/ssh.d.mts.map +0 -1
  35. package/dist/app/ssh.mjs +0 -218
  36. package/dist/app/tail.d.mts +0 -13
  37. package/dist/app/tail.d.mts.map +0 -1
  38. package/dist/app/tail.mjs +0 -168
  39. package/dist/db/analyze.d.mts +0 -3
  40. package/dist/db/analyze.d.mts.map +0 -1
  41. package/dist/db/analyze.mjs +0 -16
  42. package/dist/db/attributes.d.mts +0 -16
  43. package/dist/db/attributes.d.mts.map +0 -1
  44. package/dist/db/attributes.mjs +0 -37
  45. package/dist/db/check-constraints.d.mts +0 -9
  46. package/dist/db/check-constraints.d.mts.map +0 -1
  47. package/dist/db/check-constraints.mjs +0 -17
  48. package/dist/db/custom-types.d.mts +0 -26
  49. package/dist/db/custom-types.d.mts.map +0 -1
  50. package/dist/db/custom-types.mjs +0 -61
  51. package/dist/db/enums.d.mts +0 -8
  52. package/dist/db/enums.d.mts.map +0 -1
  53. package/dist/db/enums.mjs +0 -24
  54. package/dist/db/extensions.d.mts +0 -8
  55. package/dist/db/extensions.d.mts.map +0 -1
  56. package/dist/db/extensions.mjs +0 -14
  57. package/dist/db/file-stats.d.mts +0 -11
  58. package/dist/db/file-stats.d.mts.map +0 -1
  59. package/dist/db/file-stats.mjs +0 -43
  60. package/dist/db/foreign-keys.d.mts +0 -14
  61. package/dist/db/foreign-keys.d.mts.map +0 -1
  62. package/dist/db/foreign-keys.mjs +0 -44
  63. package/dist/db/functions.d.mts +0 -11
  64. package/dist/db/functions.d.mts.map +0 -1
  65. package/dist/db/functions.mjs +0 -23
  66. package/dist/db/index.d.mts +0 -19
  67. package/dist/db/index.d.mts.map +0 -1
  68. package/dist/db/index.mjs +0 -19
  69. package/dist/db/indexes.d.mts +0 -16
  70. package/dist/db/indexes.d.mts.map +0 -1
  71. package/dist/db/indexes.mjs +0 -38
  72. package/dist/db/planner-stats.d.mts +0 -33
  73. package/dist/db/planner-stats.d.mts.map +0 -1
  74. package/dist/db/planner-stats.mjs +0 -103
  75. package/dist/db/relations.d.mts +0 -11
  76. package/dist/db/relations.d.mts.map +0 -1
  77. package/dist/db/relations.mjs +0 -32
  78. package/dist/db/rls.d.mts +0 -21
  79. package/dist/db/rls.d.mts.map +0 -1
  80. package/dist/db/rls.mjs +0 -48
  81. package/dist/db/sample.d.mts +0 -16
  82. package/dist/db/sample.d.mts.map +0 -1
  83. package/dist/db/sample.mjs +0 -73
  84. package/dist/db/sequences.d.mts +0 -15
  85. package/dist/db/sequences.d.mts.map +0 -1
  86. package/dist/db/sequences.mjs +0 -31
  87. package/dist/db/stats.d.mts +0 -12
  88. package/dist/db/stats.d.mts.map +0 -1
  89. package/dist/db/stats.mjs +0 -34
  90. package/dist/db/triggers.d.mts +0 -11
  91. package/dist/db/triggers.d.mts.map +0 -1
  92. package/dist/db/triggers.mjs +0 -21
  93. package/dist/db/version.d.mts +0 -14
  94. package/dist/db/version.d.mts.map +0 -1
  95. package/dist/db/version.mjs +0 -27
  96. package/dist/flow/events.d.mts +0 -115
  97. package/dist/flow/events.d.mts.map +0 -1
  98. package/dist/flow/events.mjs +0 -2
  99. package/dist/flow/interpreter.d.mts +0 -21
  100. package/dist/flow/interpreter.d.mts.map +0 -1
  101. package/dist/flow/interpreter.mjs +0 -605
  102. package/dist/flow/projection.d.mts +0 -17
  103. package/dist/flow/projection.d.mts.map +0 -1
  104. package/dist/flow/projection.mjs +0 -83
  105. package/dist/flow/projection.test.d.mts +0 -2
  106. package/dist/flow/projection.test.d.mts.map +0 -1
  107. package/dist/flow/projection.test.mjs +0 -162
  108. package/dist/flow/reducer.d.mts +0 -5
  109. package/dist/flow/reducer.d.mts.map +0 -1
  110. package/dist/flow/reducer.mjs +0 -306
  111. package/dist/flow/reducer.test.d.mts +0 -2
  112. package/dist/flow/reducer.test.d.mts.map +0 -1
  113. package/dist/flow/reducer.test.mjs +0 -479
  114. package/dist/flow/run.d.mts +0 -3
  115. package/dist/flow/run.d.mts.map +0 -1
  116. package/dist/flow/run.mjs +0 -89
  117. package/dist/flow/states.d.mts +0 -54
  118. package/dist/flow/states.d.mts.map +0 -1
  119. package/dist/flow/states.mjs +0 -39
  120. package/dist/index.d.mts +0 -29
  121. package/dist/index.d.mts.map +0 -1
  122. package/dist/lib/atomic-write.d.mts +0 -4
  123. package/dist/lib/atomic-write.d.mts.map +0 -1
  124. package/dist/lib/atomic-write.mjs +0 -75
  125. package/dist/lib/env.d.mts +0 -2
  126. package/dist/lib/env.d.mts.map +0 -1
  127. package/dist/lib/env.mjs +0 -4
  128. package/dist/lib/stream-job.d.mts +0 -19
  129. package/dist/lib/stream-job.d.mts.map +0 -1
  130. package/dist/lib/stream-job.mjs +0 -55
  131. package/dist/lib/trpc-url.d.mts +0 -2
  132. package/dist/lib/trpc-url.d.mts.map +0 -1
  133. package/dist/lib/trpc-url.mjs +0 -5
  134. package/dist/lib/trpc.d.mts +0 -7
  135. package/dist/lib/trpc.d.mts.map +0 -1
  136. package/dist/lib/trpc.mjs +0 -37
  137. package/dist/lib/trpc.react.d.mts +0 -4
  138. package/dist/lib/trpc.react.d.mts.map +0 -1
  139. package/dist/lib/trpc.react.mjs +0 -3
  140. package/dist/lib/version.d.mts +0 -2
  141. package/dist/lib/version.d.mts.map +0 -1
  142. package/dist/lib/version.mjs +0 -5
  143. package/dist/logger.d.mts +0 -3
  144. package/dist/logger.d.mts.map +0 -1
  145. package/dist/logger.mjs +0 -11
  146. package/dist/providers/TrpcProvider.d.ts +0 -9
  147. package/dist/providers/TrpcProvider.d.ts.map +0 -1
  148. package/dist/providers/TrpcProvider.js +0 -41
  149. package/dist/store.d.mts +0 -176
  150. package/dist/store.d.mts.map +0 -1
  151. package/dist/store.mjs +0 -147
  152. package/dist/types/connection.d.mts +0 -17
  153. package/dist/types/connection.d.mts.map +0 -1
  154. package/dist/types/connection.mjs +0 -2
  155. package/dist/ui/App.d.ts +0 -10
  156. package/dist/ui/App.d.ts.map +0 -1
  157. package/dist/ui/App.js +0 -41
  158. package/dist/ui/components/Analyze.d.ts +0 -10
  159. package/dist/ui/components/Analyze.d.ts.map +0 -1
  160. package/dist/ui/components/Analyze.js +0 -54
  161. package/dist/ui/components/Billing.d.ts +0 -10
  162. package/dist/ui/components/Billing.d.ts.map +0 -1
  163. package/dist/ui/components/Billing.js +0 -40
  164. package/dist/ui/components/DB.d.ts +0 -10
  165. package/dist/ui/components/DB.d.ts.map +0 -1
  166. package/dist/ui/components/DB.js +0 -22
  167. package/dist/ui/components/DatabasePicker.d.ts +0 -13
  168. package/dist/ui/components/DatabasePicker.d.ts.map +0 -1
  169. package/dist/ui/components/DatabasePicker.js +0 -79
  170. package/dist/ui/components/Enrich.d.ts +0 -10
  171. package/dist/ui/components/Enrich.d.ts.map +0 -1
  172. package/dist/ui/components/Enrich.js +0 -41
  173. package/dist/ui/components/Error.d.ts +0 -7
  174. package/dist/ui/components/Error.d.ts.map +0 -1
  175. package/dist/ui/components/Error.js +0 -6
  176. package/dist/ui/components/Gate.d.ts +0 -10
  177. package/dist/ui/components/Gate.d.ts.map +0 -1
  178. package/dist/ui/components/Gate.js +0 -15
  179. package/dist/ui/components/Introspect.d.ts +0 -10
  180. package/dist/ui/components/Introspect.d.ts.map +0 -1
  181. package/dist/ui/components/Introspect.js +0 -66
  182. package/dist/ui/components/IntrospectionUpload.d.ts +0 -10
  183. package/dist/ui/components/IntrospectionUpload.d.ts.map +0 -1
  184. package/dist/ui/components/IntrospectionUpload.js +0 -30
  185. package/dist/ui/components/Login.d.ts +0 -19
  186. package/dist/ui/components/Login.d.ts.map +0 -1
  187. package/dist/ui/components/Login.js +0 -38
  188. package/dist/ui/components/OutputJson.d.ts +0 -10
  189. package/dist/ui/components/OutputJson.d.ts.map +0 -1
  190. package/dist/ui/components/OutputJson.js +0 -18
  191. package/dist/ui/components/PasswordInput.d.ts +0 -7
  192. package/dist/ui/components/PasswordInput.d.ts.map +0 -1
  193. package/dist/ui/components/PasswordInput.js +0 -32
  194. package/dist/ui/components/SSH.d.ts +0 -10
  195. package/dist/ui/components/SSH.d.ts.map +0 -1
  196. package/dist/ui/components/SSH.js +0 -22
  197. package/dist/ui/components/SamplesUpload.d.ts +0 -10
  198. package/dist/ui/components/SamplesUpload.d.ts.map +0 -1
  199. package/dist/ui/components/SamplesUpload.js +0 -24
  200. package/dist/ui/components/Sampling.d.ts +0 -10
  201. package/dist/ui/components/Sampling.d.ts.map +0 -1
  202. package/dist/ui/components/Sampling.js +0 -58
  203. package/dist/ui/components/Session.d.ts +0 -10
  204. package/dist/ui/components/Session.d.ts.map +0 -1
  205. package/dist/ui/components/Session.js +0 -47
  206. package/dist/ui/components/Spinner.d.ts +0 -3
  207. package/dist/ui/components/Spinner.d.ts.map +0 -1
  208. package/dist/ui/components/Spinner.js +0 -30
  209. package/dist/ui/components/Splash.d.ts +0 -3
  210. package/dist/ui/components/Splash.d.ts.map +0 -1
  211. package/dist/ui/components/Splash.js +0 -13
  212. package/dist/ui/components/TextInput.d.ts +0 -11
  213. package/dist/ui/components/TextInput.d.ts.map +0 -1
  214. package/dist/ui/components/TextInput.js +0 -286
  215. package/dist/ui/components/UserExplanation.d.ts +0 -10
  216. package/dist/ui/components/UserExplanation.d.ts.map +0 -1
  217. package/dist/ui/components/UserExplanation.js +0 -34
  218. package/dist/validatePaths.d.mts +0 -13
  219. package/dist/validatePaths.d.mts.map +0 -1
  220. package/dist/validatePaths.mjs +0 -58
@@ -1,605 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { TRPCClientError } from '@trpc/client';
3
- import { computeSchemaHash } from '@dbctx/common/schema-hash';
4
- import { runInAction } from 'mobx';
5
- import { connectSSH } from '../app/ssh.mjs';
6
- import { connectDB } from '../app/db.mjs';
7
- import { assembleDatabase } from '../app/assemble.mjs';
8
- import { loadIntrospectionFromFile, populateIntrospectionCounts, } from '../app/load-introspection.mjs';
9
- import { createSession, waitForAuthorization, connectAccount, checkGate, checkBilling, } from '../app/session.mjs';
10
- import { buildSessionURL } from '../app/open-url.mjs';
11
- import { readConfig, flushConfig } from '../app/config.mjs';
12
- import { runSampling, prepareOutputDir, persistTableSamplesToDir, loadSensitiveMask, } from '../app/sample.mjs';
13
- import { fetchPublicPlannerStatistics } from '../db/index.mjs';
14
- import { createAuthenticatedTRPCClient } from '../lib/trpc.mjs';
15
- import { streamPostIntrospection, dispatchAndStreamPostSampling, } from '../app/tail.mjs';
16
- import { atomicWriteFile, recoverAtomicWrite } from '../lib/atomic-write.mjs';
17
- import { DBCTX_DEV } from '../lib/env.mjs';
18
- import { logger } from '../logger.mjs';
19
- import { when } from 'mobx';
20
- export const initialContext = () => ({
21
- cleanupSSH: null,
22
- db: null,
23
- introspection: null,
24
- authed: null,
25
- postIntrospectionPoll: null,
26
- explanation: null,
27
- });
28
- const errMsg = (e) => e instanceof Error ? e.message : String(e);
29
- // Pulls the structured `dbctx` payload tRPC's errorFormatter promotes onto
30
- // shape.data. Returns null for non-tRPC errors or non-gate errors so callers
31
- // can fall back to the prose `message`.
32
- const extractGateError = (e) => {
33
- if (!(e instanceof TRPCClientError)) {
34
- return null;
35
- }
36
- const data = e.data;
37
- return data?.dbctx ?? null;
38
- };
39
- // Dispatches an ingest-failed event and, if the error carries structured
40
- // gate data, parks it on the store so the UI can render a tailored layout
41
- // instead of the prose `message`. The gate field sits outside the flow
42
- // projection on purpose — projection only owns `state`/`error`.
43
- const dispatchIngestFailed = (err, dispatch, store) => {
44
- const gate = extractGateError(err);
45
- if (gate !== null) {
46
- runInAction(() => {
47
- store.steps.ingestion.introspection.gate = gate;
48
- });
49
- }
50
- dispatch({ kind: 'ingest-failed', error: errMsg(err) });
51
- };
52
- // Single phase transition handler. Called once per (prev → curr) phase
53
- // change with prev !== curr. Each branch fires the side effects for the
54
- // new phase and dispatches event(s) back when async work resolves.
55
- export const driveSide = async (prev, curr, store, ctx, dispatch) => {
56
- if (prev !== null && prev.phase === curr.phase) {
57
- // Side-channel sub-status updates don't trigger effects.
58
- return;
59
- }
60
- if (curr.phase === 'connecting-ssh') {
61
- try {
62
- ctx.cleanupSSH = (await connectSSH(store)) ?? null;
63
- // connectSSH may set enabled=false when no ssh flag was passed.
64
- if (!store.steps.sshConnection.enabled) {
65
- dispatch({ kind: 'ssh-not-needed' });
66
- return;
67
- }
68
- await when(() => {
69
- const s = store.steps.sshConnection.state;
70
- return s === 'connected' || s === 'error';
71
- });
72
- const finalState = store.steps.sshConnection.state;
73
- if (finalState === 'error') {
74
- dispatch({
75
- kind: 'ssh-failed',
76
- error: store.steps.sshConnection.error ?? 'ssh failed',
77
- });
78
- return;
79
- }
80
- dispatch({ kind: 'ssh-connected' });
81
- }
82
- catch (err) {
83
- dispatch({ kind: 'ssh-failed', error: errMsg(err) });
84
- }
85
- return;
86
- }
87
- if (curr.phase === 'connecting-db') {
88
- try {
89
- ctx.db = (await connectDB(store)) ?? null;
90
- await when(() => {
91
- const s = store.steps.databaseConnection.state;
92
- return s === 'connected' || s === 'error';
93
- });
94
- const dbState = store.steps.databaseConnection.state;
95
- if (dbState === 'error' || ctx.db === null) {
96
- dispatch({
97
- kind: 'db-failed',
98
- error: store.steps.databaseConnection.error ?? 'db failed',
99
- });
100
- return;
101
- }
102
- dispatch({ kind: 'db-connected' });
103
- }
104
- catch (err) {
105
- dispatch({ kind: 'db-failed', error: errMsg(err) });
106
- }
107
- return;
108
- }
109
- if (curr.phase === 'introspecting') {
110
- if (ctx.db === null) {
111
- dispatch({
112
- kind: 'introspection-failed',
113
- error: 'no db connection',
114
- });
115
- return;
116
- }
117
- try {
118
- const useJsonPath = store.outputOptions.useIntrospectionJsonPath;
119
- if (useJsonPath !== null) {
120
- runInAction(() => {
121
- store.steps.introspection.state = 'fetching';
122
- });
123
- const loaded = await loadIntrospectionFromFile(useJsonPath, ctx.db.pool);
124
- if (!loaded.ok) {
125
- runInAction(() => {
126
- store.steps.introspection.state = 'error';
127
- store.steps.introspection.error = loaded.error.message;
128
- });
129
- dispatch({
130
- kind: 'introspection-failed',
131
- error: loaded.error.message,
132
- });
133
- return;
134
- }
135
- populateIntrospectionCounts(store, loaded.result);
136
- runInAction(() => {
137
- store.steps.introspection.state = 'done';
138
- });
139
- ctx.introspection = loaded.result;
140
- }
141
- else {
142
- ctx.introspection = await assembleDatabase(ctx.db.pool, store);
143
- }
144
- if (DBCTX_DEV) {
145
- const { databaseIntrospectionSchema } = await import('@dbctx/core/schemas/introspection');
146
- databaseIntrospectionSchema.parse(ctx.introspection);
147
- }
148
- dispatch({ kind: 'introspection-loaded' });
149
- }
150
- catch (err) {
151
- dispatch({ kind: 'introspection-failed', error: errMsg(err) });
152
- }
153
- return;
154
- }
155
- if (curr.phase === 'output-json') {
156
- const outputPath = curr.outputJSONPath;
157
- if (outputPath === null || ctx.introspection === null) {
158
- dispatch({ kind: 'output-json-not-requested' });
159
- return;
160
- }
161
- try {
162
- await recoverAtomicWrite(outputPath);
163
- if (existsSync(outputPath) &&
164
- !store.outputOptions.allowIntrospectionJsonOverwrite) {
165
- runInAction(() => {
166
- store.steps.outputJson.state = 'prompting-overwrite';
167
- store.steps.outputJson.path = outputPath;
168
- });
169
- await when(() => store.steps.outputJson.confirmed !== null);
170
- if (!store.steps.outputJson.confirmed) {
171
- dispatch({ kind: 'output-json-skipped' });
172
- return;
173
- }
174
- }
175
- runInAction(() => {
176
- store.steps.outputJson.state = 'writing';
177
- store.steps.outputJson.path = outputPath;
178
- });
179
- await atomicWriteFile(outputPath, JSON.stringify(ctx.introspection, null, 2));
180
- runInAction(() => {
181
- store.steps.outputJson.state = 'done';
182
- });
183
- dispatch({ kind: 'output-json-written' });
184
- }
185
- catch (err) {
186
- runInAction(() => {
187
- store.steps.outputJson.state = 'error';
188
- store.steps.outputJson.error = errMsg(err);
189
- });
190
- dispatch({ kind: 'output-json-failed', error: errMsg(err) });
191
- }
192
- return;
193
- }
194
- if (curr.phase === 'creating-session') {
195
- if (ctx.db === null || ctx.introspection === null) {
196
- dispatch({
197
- kind: 'session-failed',
198
- error: 'no db or introspection in context',
199
- });
200
- return;
201
- }
202
- try {
203
- const config = await readConfig();
204
- const sessionId = await createSession(ctx.db.pool, ctx.introspection, store, config.token ?? null, config.device_id);
205
- // Re-auth fast-path: if existing config token is still valid,
206
- // skip the browser-auth handshake entirely.
207
- if (config.token) {
208
- try {
209
- await connectAccount(config.token, store);
210
- await checkBilling(config.token, buildSessionURL(sessionId), store);
211
- const canContinue = await checkGate(config.token, store);
212
- if (!canContinue) {
213
- dispatch({ kind: 'auth-not-needed' });
214
- return;
215
- }
216
- // Single dispatch carrying both sessionId and token.
217
- // Avoids transitioning through awaiting-authorization,
218
- // which would race-fire waitForAuthorization and stomp
219
- // the already-'connected' account state back to 'waiting'.
220
- dispatch({
221
- kind: 'fast-path-completed',
222
- sessionId,
223
- token: config.token,
224
- });
225
- return;
226
- }
227
- catch (err) {
228
- if (err instanceof TRPCClientError &&
229
- (err.data?.code === 'UNAUTHORIZED' ||
230
- err.data?.code === 'NOT_FOUND')) {
231
- await flushConfig();
232
- }
233
- else {
234
- throw err;
235
- }
236
- }
237
- }
238
- dispatch({ kind: 'session-created', sessionId });
239
- }
240
- catch (err) {
241
- dispatch({ kind: 'session-failed', error: errMsg(err) });
242
- }
243
- return;
244
- }
245
- if (curr.phase === 'awaiting-authorization') {
246
- if (curr.sessionId === null) {
247
- dispatch({ kind: 'auth-failed', error: 'no sessionId in state' });
248
- return;
249
- }
250
- try {
251
- await waitForAuthorization(curr.sessionId, store);
252
- const freshToken = (await readConfig()).token;
253
- if (!freshToken) {
254
- dispatch({ kind: 'auth-failed', error: 'no token after auth' });
255
- return;
256
- }
257
- await checkBilling(freshToken, buildSessionURL(curr.sessionId), store);
258
- const canContinue = await checkGate(freshToken, store);
259
- if (!canContinue) {
260
- dispatch({ kind: 'auth-failed', error: 'gate blocked' });
261
- return;
262
- }
263
- dispatch({ kind: 'auth-confirmed', token: freshToken });
264
- }
265
- catch (err) {
266
- dispatch({ kind: 'auth-failed', error: errMsg(err) });
267
- }
268
- return;
269
- }
270
- if (curr.phase === 'awaiting-explanation') {
271
- if (curr.explanation !== null) {
272
- ctx.explanation = curr.explanation;
273
- runInAction(() => {
274
- store.steps.userExplanation.state = 'done';
275
- store.steps.userExplanation.value = curr.explanation;
276
- });
277
- dispatch({
278
- kind: 'explanation-given',
279
- value: curr.explanation,
280
- });
281
- return;
282
- }
283
- runInAction(() => {
284
- store.steps.userExplanation.state = 'prompting';
285
- });
286
- await when(() => store.steps.userExplanation.state === 'done');
287
- const v = store.steps.userExplanation.value ?? '';
288
- ctx.explanation = v;
289
- dispatch({ kind: 'explanation-given', value: v });
290
- return;
291
- }
292
- if (curr.phase === 'preflight-checking') {
293
- if (ctx.db === null ||
294
- ctx.introspection === null ||
295
- curr.authToken === null ||
296
- curr.sessionId === null) {
297
- dispatch({
298
- kind: 'ingest-failed',
299
- error: 'context not ready for preflight',
300
- });
301
- return;
302
- }
303
- try {
304
- ctx.authed = createAuthenticatedTRPCClient(() => Promise.resolve(curr.authToken));
305
- const explanation = ctx.explanation ?? curr.explanation;
306
- if (explanation !== null) {
307
- ctx.introspection.userExplanation = explanation;
308
- }
309
- const plannerStats = await fetchPublicPlannerStatistics(ctx.db.pool);
310
- const introspectionHash = computeSchemaHash(ctx.introspection);
311
- const checkHit = await ctx.authed.revisions.checkIntrospection.mutate({
312
- sessionId: curr.sessionId,
313
- introspectionHash,
314
- systemIdentifier: ctx.introspection.identifier.system_identifier,
315
- databaseOID: String(ctx.introspection.identifier.database_oid),
316
- plannerStatistics: { relations: plannerStats },
317
- });
318
- if (checkHit !== null) {
319
- runInAction(() => {
320
- store.landingURL = checkHit.landingURL;
321
- });
322
- kickPostIntrospectionPoll(ctx, checkHit.postIntrospectionJobId, store);
323
- dispatch({
324
- kind: 'check-introspection-hit',
325
- revisionId: checkHit.revisionId,
326
- samplesExist: checkHit.samplesExist,
327
- tablesNeedingSamples: checkHit.tablesNeedingSamples,
328
- postIntrospectionJobId: checkHit.postIntrospectionJobId,
329
- });
330
- return;
331
- }
332
- dispatch({ kind: 'check-introspection-miss' });
333
- }
334
- catch (err) {
335
- dispatchIngestFailed(err, dispatch, store);
336
- }
337
- return;
338
- }
339
- if (curr.phase === 'ingesting-introspection') {
340
- if (ctx.authed === null ||
341
- ctx.introspection === null ||
342
- curr.sessionId === null ||
343
- ctx.db === null) {
344
- dispatch({
345
- kind: 'ingest-failed',
346
- error: 'context not ready for ingest',
347
- });
348
- return;
349
- }
350
- try {
351
- runInAction(() => {
352
- store.steps.ingestion.introspection.state = 'uploading';
353
- });
354
- const plannerStats = await fetchPublicPlannerStatistics(ctx.db.pool);
355
- const ingest = await ctx.authed.revisions.ingestIntrospection.mutate({
356
- sessionId: curr.sessionId,
357
- introspection: ctx.introspection,
358
- plannerStatistics: { relations: plannerStats },
359
- });
360
- runInAction(() => {
361
- store.landingURL = ingest.landingURL;
362
- });
363
- kickPostIntrospectionPoll(ctx, ingest.postIntrospectionJobId, store);
364
- dispatch({
365
- kind: 'introspection-ingested',
366
- revisionId: ingest.revisionId,
367
- samplesExist: ingest.samplesExist,
368
- tablesNeedingSamples: ingest.tablesNeedingSamples,
369
- postIntrospectionJobId: ingest.postIntrospectionJobId,
370
- });
371
- }
372
- catch (err) {
373
- dispatchIngestFailed(err, dispatch, store);
374
- }
375
- return;
376
- }
377
- if (curr.phase === 'sampling-mask-resolving') {
378
- if (ctx.authed === null ||
379
- curr.revisionId === null ||
380
- ctx.introspection === null) {
381
- dispatch({
382
- kind: 'mask-fetch-failed',
383
- error: 'context not ready for mask resolution',
384
- });
385
- return;
386
- }
387
- try {
388
- const fileMaskPath = curr.fileMaskPath;
389
- if (fileMaskPath !== null) {
390
- const mask = await loadSensitiveMask(fileMaskPath);
391
- dispatch({ kind: 'mask-loaded', mask });
392
- return;
393
- }
394
- // Server-managed mask: wait for post-introspection to finish.
395
- if (ctx.postIntrospectionPoll !== null) {
396
- await ctx.postIntrospectionPoll;
397
- ctx.postIntrospectionPoll = null;
398
- }
399
- // After the await, sub-status reflects post-introspection state.
400
- // The reducer's projection won't have re-fired driveSide on its own
401
- // (sub-status only). Inspect store directly.
402
- if (store.steps.ingestion.postIntrospection.state === 'error') {
403
- dispatch({
404
- kind: 'mask-fetch-failed',
405
- error: 'post-introspection enrichment failed — sensitive mask unavailable; refusing to sample',
406
- });
407
- return;
408
- }
409
- const res = await ctx.authed.revisions.getSensitiveMask.query({
410
- revisionId: curr.revisionId,
411
- });
412
- if (!res.ready) {
413
- dispatch({
414
- kind: 'mask-fetch-failed',
415
- error: 'server reported sensitive mask not ready after post-introspection completion; refusing to sample',
416
- });
417
- return;
418
- }
419
- dispatch({ kind: 'mask-loaded', mask: res.mask });
420
- }
421
- catch (err) {
422
- dispatch({ kind: 'mask-fetch-failed', error: errMsg(err) });
423
- }
424
- return;
425
- }
426
- if (curr.phase === 'sampling') {
427
- if (ctx.db === null ||
428
- ctx.introspection === null ||
429
- curr.sampling.mask === null) {
430
- dispatch({
431
- kind: 'sampling-failed',
432
- error: 'context not ready for sampling',
433
- });
434
- return;
435
- }
436
- try {
437
- const mask = curr.sampling.mask;
438
- const sampleFileIndex = {};
439
- const outputDir = curr.outputSamplesDir;
440
- if (outputDir !== null) {
441
- const ready = await prepareOutputDir(outputDir, store.outputOptions.allowSampleOverwrite, store);
442
- if (!ready) {
443
- dispatch({
444
- kind: 'sampling-failed',
445
- error: 'output dir not ready',
446
- });
447
- return;
448
- }
449
- }
450
- // Filter the per-table sampling loop to only the tables the
451
- // server flagged as needing fresh samples. Null = pre-handshake
452
- // sentinel; treat as "all tables" for safety.
453
- const tableFilter = curr.tablesNeedingSamples === null
454
- ? undefined
455
- : new Set(curr.tablesNeedingSamples);
456
- for await (const event of runSampling(ctx.db.pool, ctx.introspection, store, mask, tableFilter)) {
457
- if (outputDir !== null) {
458
- await persistTableSamplesToDir(outputDir, event, sampleFileIndex);
459
- }
460
- dispatch({ kind: 'sample-table-yielded', event });
461
- }
462
- dispatch({ kind: 'sampling-completed' });
463
- }
464
- catch (err) {
465
- dispatch({ kind: 'sampling-failed', error: errMsg(err) });
466
- }
467
- return;
468
- }
469
- if (curr.phase === 'uploading-samples') {
470
- if (ctx.authed === null || curr.revisionId === null) {
471
- dispatch({
472
- kind: 'samples-upload-failed',
473
- error: 'context not ready for upload',
474
- });
475
- return;
476
- }
477
- try {
478
- const samples = curr.sampling.collected;
479
- if (samples.length === 0) {
480
- runInAction(() => {
481
- store.steps.ingestion.samples.state = 'done';
482
- });
483
- dispatch({ kind: 'samples-upload-not-needed' });
484
- return;
485
- }
486
- const sampleInputs = samples.map((event) => ({
487
- tableName: event.tableName,
488
- columns: Object.fromEntries(Object.entries(event.samples.columns).map(([col, s]) => [
489
- col,
490
- [...s.values],
491
- ])),
492
- }));
493
- const CHUNK_SIZE = 25;
494
- runInAction(() => {
495
- store.steps.ingestion.samples.state = 'uploading';
496
- store.steps.ingestion.samples.totalTables = sampleInputs.length;
497
- store.steps.ingestion.samples.uploadedTables = 0;
498
- });
499
- const chunks = Array.from({ length: Math.ceil(sampleInputs.length / CHUNK_SIZE) }, (_, i) => sampleInputs.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE));
500
- for (let i = 0; i < chunks.length; i++) {
501
- const chunk = chunks[i];
502
- await ctx.authed.revisions.ingestSamples.mutate({
503
- revisionId: curr.revisionId,
504
- samples: chunk,
505
- chunkIndex: i,
506
- chunkTotal: chunks.length,
507
- });
508
- runInAction(() => {
509
- store.steps.ingestion.samples.uploadedTables +=
510
- chunk.length;
511
- });
512
- dispatch({
513
- kind: 'sample-chunk-uploaded',
514
- chunkSize: chunk.length,
515
- });
516
- }
517
- runInAction(() => {
518
- store.steps.ingestion.samples.state = 'done';
519
- });
520
- logger.info(`ingested ${sampleInputs.length} sample tables in ${chunks.length} chunk(s)`);
521
- dispatch({ kind: 'samples-upload-completed' });
522
- }
523
- catch (err) {
524
- dispatch({ kind: 'samples-upload-failed', error: errMsg(err) });
525
- }
526
- return;
527
- }
528
- if (curr.phase === 'awaiting-post-sampling') {
529
- if (ctx.authed === null || curr.revisionId === null) {
530
- dispatch({
531
- kind: 'post-sampling-failed',
532
- error: 'context not ready',
533
- });
534
- return;
535
- }
536
- try {
537
- // First ensure post-introspection finished (file-mask fast path may
538
- // have skipped the explicit await earlier).
539
- if (ctx.postIntrospectionPoll !== null) {
540
- await ctx.postIntrospectionPoll;
541
- ctx.postIntrospectionPoll = null;
542
- }
543
- if (store.steps.ingestion.postIntrospection.state === 'error') {
544
- runInAction(() => {
545
- store.steps.ingestion.postSampling.state = 'error';
546
- store.steps.ingestion.postSampling.error =
547
- 'skipped — post-introspection enrichment failed';
548
- });
549
- dispatch({
550
- kind: 'post-sampling-failed',
551
- error: 'post-introspection enrichment failed',
552
- });
553
- return;
554
- }
555
- await dispatchAndStreamPostSampling(ctx.authed, curr.revisionId, store);
556
- if (store.steps.ingestion.postSampling.state === 'error') {
557
- dispatch({
558
- kind: 'post-sampling-failed',
559
- error: store.steps.ingestion.postSampling.error ??
560
- 'post-sampling failed',
561
- });
562
- return;
563
- }
564
- dispatch({ kind: 'post-sampling-completed' });
565
- }
566
- catch (err) {
567
- dispatch({ kind: 'post-sampling-failed', error: errMsg(err) });
568
- }
569
- return;
570
- }
571
- if (curr.phase === 'done' || curr.phase === 'error') {
572
- cleanup(ctx);
573
- return;
574
- }
575
- };
576
- const kickPostIntrospectionPoll = (ctx, jobId, store) => {
577
- runInAction(() => {
578
- if (jobId === null) {
579
- store.steps.ingestion.postIntrospection.state = 'done';
580
- store.steps.ingestion.postIntrospection.reused = true;
581
- }
582
- else {
583
- store.steps.ingestion.postIntrospection.jobId = jobId;
584
- if (store.steps.ingestion.postIntrospection.state === 'idle') {
585
- store.steps.ingestion.postIntrospection.state = 'queued';
586
- }
587
- }
588
- });
589
- if (jobId === null || ctx.authed === null) {
590
- ctx.postIntrospectionPoll = Promise.resolve();
591
- return;
592
- }
593
- ctx.postIntrospectionPoll = streamPostIntrospection(ctx.authed, jobId, store).then(() => { }, () => { });
594
- };
595
- export const cleanup = (ctx) => {
596
- if (ctx.db !== null) {
597
- ctx.db.cleanup();
598
- ctx.db = null;
599
- }
600
- if (ctx.cleanupSSH !== null) {
601
- ctx.cleanupSSH();
602
- ctx.cleanupSSH = null;
603
- }
604
- };
605
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJwcmV0ZXIubWpzIiwic291cmNlUm9vdCI6Ii4vc3JjLyIsInNvdXJjZXMiOlsiZmxvdy9pbnRlcnByZXRlci5tdHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUduQyxPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBQzVELE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDakMsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQzFDLE9BQU8sRUFBQyxTQUFTLEVBQXFCLE1BQU0sZUFBZSxDQUFDO0FBQzVELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBQ3JELE9BQU8sRUFDSCx5QkFBeUIsRUFDekIsMkJBQTJCLEdBQzlCLE1BQU0sK0JBQStCLENBQUM7QUFDdkMsT0FBTyxFQUNILGFBQWEsRUFDYixvQkFBb0IsRUFDcEIsY0FBYyxFQUNkLFNBQVMsRUFDVCxZQUFZLEdBQ2YsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUMxRCxPQUFPLEVBQ0gsV0FBVyxFQUNYLGdCQUFnQixFQUNoQix3QkFBd0IsRUFDeEIsaUJBQWlCLEdBRXBCLE1BQU0sbUJBQW1CLENBQUM7QUFDM0IsT0FBTyxFQUFDLDRCQUE0QixFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDN0QsT0FBTyxFQUFDLDZCQUE2QixFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDOUQsT0FBTyxFQUNILHVCQUF1QixFQUN2Qiw2QkFBNkIsR0FDaEMsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVB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QUMsaUJBQWlCLENBQUMsS0FBSyxLQUFLLE1BQU0sRUFBRSxDQUFDO2dCQUMzRCxLQUFLLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFDO1lBQzdELENBQUM7UUFDTCxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDSCxJQUFJLEtBQUssS0FBSyxJQUFJLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUN4QyxHQUFHLENBQUMscUJBQXFCLEdBQUcsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzlDLE9BQU87SUFDWCxDQUFDO0lBQ0QsR0FBRyxDQUFDLHFCQUFxQixHQUFHLHVCQUF1QixDQUMvQyxHQUFHLENBQUMsTUFBTSxFQUNWLEtBQUssRUFDTCxLQUFLLENBQ1IsQ0FBQyxJQUFJLENBQ0YsR0FBRyxFQUFFLEdBQUUsQ0FBQyxFQUNSLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FDWCxDQUFDO0FBQ04sQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sT0FBTyxHQUFHLENBQUMsR0FBd0IsRUFBUSxFQUFFO0lBQ3RELElBQUksR0FBRyxDQUFDLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUNsQixHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2pCLEdBQUcsQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDO0lBQ2xCLENBQUM7SUFDRCxJQUFJLEdBQUcsQ0FBQyxVQUFVLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDMUIsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2pCLEdBQUcsQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDO0lBQzFCLENBQUM7QUFDTCxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2V4aXN0c1N5bmN9IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHR5cGUge1RSUENDbGllbnR9IGZyb20gJ0B0cnBjL2NsaWVudCc7XG5pbXBvcnQgdHlwZSB7VEFwcFJvdXRlciwgVEdhdGVFcnJvckRhdGF9IGZyb20gJ0BkYmN0eC9jb3JlJztcbmltcG9ydCB7VFJQQ0NsaWVudEVycm9yfSBmcm9tICdAdHJwYy9jbGllbnQnO1xuaW1wb3J0IHtjb21wdXRlU2NoZW1hSGFzaH0gZnJvbSAnQGRiY3R4L2NvbW1vbi9zY2hlbWEtaGFzaCc7XG5pbXBvcnQge3J1bkluQWN0aW9ufSBmcm9tICdtb2J4JztcbmltcG9ydCB7Y29ubmVjdFNTSH0gZnJvbSAnLi4vYXBwL3NzaC5tanMnO1xuaW1wb3J0IHtjb25uZWN0REIsIHR5cGUgVERCQ29ubmVjdGlvbn0gZnJvbSAnLi4vYXBwL2RiLm1qcyc7XG5pbXBvcnQge2Fzc2VtYmxlRGF0YWJhc2V9IGZyb20gJy4uL2FwcC9hc3NlbWJsZS5tanMnO1xuaW1wb3J0IHtcbiAgICBsb2FkSW50cm9zcGVjdGlvbkZyb21GaWxlLFxuICAgIHBvcHVsYXRlSW50cm9zcGVjdGlvbkNvdW50cyxcbn0gZnJvbSAnLi4vYXBwL2xvYWQtaW50cm9zcGVjdGlvbi5tanMnO1xuaW1wb3J0IHtcbiAgICBjcmVhdGVTZXNzaW9uLFxuICAgIHdhaXRGb3JBdXRob3JpemF0aW9uLFxuICAgIGNvbm5lY3RBY2NvdW50LFxuICAgIGNoZWNrR2F0ZSxcbiAgICBjaGVja0JpbGxpbmcsXG59IGZyb20gJy4uL2FwcC9zZXNzaW9uLm1qcyc7XG5pbXBvcnQge2J1aWxkU2Vzc2lvblVSTH0gZnJvbSAnLi4vYXBwL29wZW4tdXJsLm1qcyc7XG5pbXBvcnQge3JlYWRDb25maWcsIGZsdXNoQ29uZmlnfSBmcm9tICcuLi9hcHAvY29uZmlnLm1qcyc7XG5pbXBvcnQge1xuICAgIHJ1blNhbXBsaW5nLFxuICAgIHByZXBhcmVPdXRwdXREaXIsXG4gICAgcGVyc2lzdFRhYmxlU2FtcGxlc1RvRGlyLFxuICAgIGxvYWRTZW5zaXRpdmVNYXNrLFxuICAgIHR5cGUgVFNlbnNpdGl2ZU1hc2ssXG59IGZyb20gJy4uL2FwcC9zYW1wbGUubWpzJztcbmltcG9ydCB7ZmV0Y2hQdWJsaWNQbGFubmVyU3RhdGlzdGljc30gZnJvbSAnLi4vZGIvaW5kZXgubWpzJztcbmltcG9ydCB7Y3JlYXRlQXV0aGVudGljYXRlZFRSUENDbGllbnR9IGZyb20gJy4uL2xpYi90cnBjLm1qcyc7XG5pbXBvcnQge1xuICAgIHN0cmVhbVBvc3RJbnRyb3NwZWN0aW9uLFxuICAgIGRpc3BhdGNoQW5kU3RyZWFtUG9zdFNhbXBsaW5nLFxufSBmcm9tICcuLi9hcHAvdGFpbC5tanMnO1xuaW1wb3J0IHthdG9taWNXcml0ZUZpbGUsIHJlY292ZXJBdG9taWNXcml0ZX0gZnJvbSAnLi4vbGliL2F0b21pYy13cml0ZS5tanMnO1xuaW1wb3J0IHtEQkNUWF9ERVZ9IGZyb20gJy4uL2xpYi9lbnYubWpzJztcbmltcG9ydCB7bG9nZ2VyfSBmcm9tICcuLi9sb2dnZXIubWpzJztcbmltcG9ydCB0eXBlIHtUU3RvcmV9IGZyb20gJy4uL3N0b3JlLm1qcyc7XG5pbXBvcnQgdHlwZSB7VEZsb3dFdmVudH0gZnJvbSAnLi9ldmVudHMubWpzJztcbmltcG9ydCB0eXBlIHtURmxvd1N0YXRlfSBmcm9tICcuL3N0YXRlcy5tanMnO1xuaW1wb3J0IHt3aGVufSBmcm9tICdtb2J4JztcblxuLy8gRWZmZWN0IGhhbmRsZXMgdGhlIGludGVycHJldGVyIGFjY3VtdWxhdGVzIGFzIHRoZSBmbG93IGFkdmFuY2VzLiBOb3Rcbi8vIHBhcnQgb2YgVEZsb3dTdGF0ZSBiZWNhdXNlIHRoZXkgYXJlbid0IHB1cmUgZGF0YSDigJQgUHJvbWlzZSBoYW5kbGVzLCBEQlxuLy8gcG9vbHMsIGNsZWFudXAgY2FsbGJhY2tzLiBUaGUgZGlzcGF0Y2hlciBjbG9zZXMgb3ZlciB0aGlzIGNvbnRleHQuXG5leHBvcnQgdHlwZSBUSW50ZXJwcmV0ZXJDb250ZXh0ID0ge1xuICAgIGNsZWFudXBTU0g6ICgoKSA9PiB2b2lkKSB8IG51bGw7XG4gICAgZGI6IFREQkNvbm5lY3Rpb24gfCBudWxsO1xuICAgIGludHJvc3BlY3Rpb246IEF3YWl0ZWQ8UmV0dXJuVHlwZTx0eXBlb2YgYXNzZW1ibGVEYXRhYmFzZT4+IHwgbnVsbDtcbiAgICBhdXRoZWQ6IFRSUENDbGllbnQ8VEFwcFJvdXRlcj4gfCBudWxsO1xuICAgIHBvc3RJbnRyb3NwZWN0aW9uUG9sbDogUHJvbWlzZTx2b2lkPiB8IG51bGw7XG4gICAgZXhwbGFuYXRpb246IHN0cmluZyB8IG51bGw7XG59O1xuXG5leHBvcnQgY29uc3QgaW5pdGlhbENvbnRleHQgPSAoKTogVEludGVycHJldGVyQ29udGV4dCA9PiAoe1xuICAgIGNsZWFudXBTU0g6IG51bGwsXG4gICAgZGI6IG51bGwsXG4gICAgaW50cm9zcGVjdGlvbjogbnVsbCxcbiAgICBhdXRoZWQ6IG51bGwsXG4gICAgcG9zdEludHJvc3BlY3Rpb25Qb2xsOiBudWxsLFxuICAgIGV4cGxhbmF0aW9uOiBudWxsLFxufSk7XG5cbnR5cGUgVERpc3BhdGNoID0gKGV2ZW50OiBURmxvd0V2ZW50KSA9PiB2b2lkO1xuXG5jb25zdCBlcnJNc2cgPSAoZTogdW5rbm93bik6IHN0cmluZyA9PlxuICAgIGUgaW5zdGFuY2VvZiBFcnJvciA/IGUubWVzc2FnZSA6IFN0cmluZyhlKTtcblxuLy8gUHVsbHMgdGhlIHN0cnVjdHVyZWQgYGRiY3R4YCBwYXlsb2FkIHRSUEMncyBlcnJvckZvcm1hdHRlciBwcm9tb3RlcyBvbnRvXG4vLyBzaGFwZS5kYXRhLiBSZXR1cm5zIG51bGwgZm9yIG5vbi10UlBDIGVycm9ycyBvciBub24tZ2F0ZSBlcnJvcnMgc28gY2FsbGVyc1xuLy8gY2FuIGZhbGwgYmFjayB0byB0aGUgcHJvc2UgYG1lc3NhZ2VgLlxuY29uc3QgZXh0cmFjdEdhdGVFcnJvciA9IChlOiB1bmtub3duKTogVEdhdGVFcnJvckRhdGEgfCBudWxsID0+IHtcbiAgICBpZiAoIShlIGluc3RhbmNlb2YgVFJQQ0NsaWVudEVycm9yKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3QgZGF0YSA9IGUuZGF0YSBhcyB7ZGJjdHg/OiBUR2F0ZUVycm9yRGF0YSB8IG51bGx9IHwgdW5kZWZpbmVkO1xuICAgIHJldHVybiBkYXRhPy5kYmN0eCA/PyBudWxsO1xufTtcblxuLy8gRGlzcGF0Y2hlcyBhbiBpbmdlc3QtZmFpbGVkIGV2ZW50IGFuZCwgaWYgdGhlIGVycm9yIGNhcnJpZXMgc3RydWN0dXJlZFxuLy8gZ2F0ZSBkYXRhLCBwYXJrcyBpdCBvbiB0aGUgc3RvcmUgc28gdGhlIFVJIGNhbiByZW5kZXIgYSB0YWlsb3JlZCBsYXlvdXRcbi8vIGluc3RlYWQgb2YgdGhlIHByb3NlIGBtZXNzYWdlYC4gVGhlIGdhdGUgZmllbGQgc2l0cyBvdXRzaWRlIHRoZSBmbG93XG4vLyBwcm9qZWN0aW9uIG9uIHB1cnBvc2Ug4oCUIHByb2plY3Rpb24gb25seSBvd25zIGBzdGF0ZWAvYGVycm9yYC5cbmNvbnN0IGRpc3BhdGNoSW5nZXN0RmFpbGVkID0gKFxuICAgIGVycjogdW5rbm93bixcbiAgICBkaXNwYXRjaDogVERpc3BhdGNoLFxuICAgIHN0b3JlOiBUU3RvcmUsXG4pOiB2b2lkID0+IHtcbiAgICBjb25zdCBnYXRlID0gZXh0cmFjdEdhdGVFcnJvcihlcnIpO1xuICAgIGlmIChnYXRlICE9PSBudWxsKSB7XG4gICAgICAgIHJ1bkluQWN0aW9uKCgpID0+IHtcbiAgICAgICAgICAgIHN0b3JlLnN0ZXBzLmluZ2VzdGlvbi5pbnRyb3NwZWN0aW9uLmdhdGUgPSBnYXRlO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZGlzcGF0Y2goe2tpbmQ6ICdpbmdlc3QtZmFpbGVkJywgZXJyb3I6IGVyck1zZyhlcnIpfSk7XG59O1xuXG4vLyBTaW5nbGUgcGhhc2UgdHJhbnNpdGlvbiBoYW5kbGVyLiBDYWxsZWQgb25jZSBwZXIgKHByZXYg4oaSIGN1cnIpIHBoYXNlXG4vLyBjaGFuZ2Ugd2l0aCBwcmV2ICE9PSBjdXJyLiBFYWNoIGJyYW5jaCBmaXJlcyB0aGUgc2lkZSBlZmZlY3RzIGZvciB0aGVcbi8vIG5ldyBwaGFzZSBhbmQgZGlzcGF0Y2hlcyBldmVudChzKSBiYWNrIHdoZW4gYXN5bmMgd29yayByZXNvbHZlcy5cbmV4cG9ydCBjb25zdCBkcml2ZVNpZGUgPSBhc3luYyAoXG4gICAgcHJldjogVEZsb3dTdGF0ZSB8IG51bGwsXG4gICAgY3VycjogVEZsb3dTdGF0ZSxcbiAgICBzdG9yZTogVFN0b3JlLFxuICAgIGN0eDogVEludGVycHJldGVyQ29udGV4dCxcbiAgICBkaXNwYXRjaDogVERpc3BhdGNoLFxuKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgaWYgKHByZXYgIT09IG51bGwgJiYgcHJldi5waGFzZSA9PT0gY3Vyci5waGFzZSkge1xuICAgICAgICAvLyBTaWRlLWNoYW5uZWwgc3ViLXN0YXR1cyB1cGRhdGVzIGRvbid0IHRyaWdnZXIgZWZmZWN0cy5cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjdXJyLnBoYXNlID09PSAnY29ubmVjdGluZy1zc2gnKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjdHguY2xlYW51cFNTSCA9IChhd2FpdCBjb25uZWN0U1NIKHN0b3JlKSkgPz8gbnVsbDtcbiAgICAgICAgICAgIC8vIGNvbm5lY3RTU0ggbWF5IHNldCBlbmFibGVkPWZhbHNlIHdoZW4gbm8gc3NoIGZsYWcgd2FzIHBhc3NlZC5cbiAgICAgICAgICAgIGlmICghc3RvcmUuc3RlcHMuc3NoQ29ubmVjdGlvbi5lbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgZGlzcGF0Y2goe2tpbmQ6ICdzc2gtbm90LW5lZWRlZCd9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCB3aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzOiBzdHJpbmcgPSBzdG9yZS5zdGVwcy5zc2hDb25uZWN0aW9uLnN0YXRlO1xuICAgICAgICAgICAgICAgIHJldHVybiBzID09PSAnY29ubmVjdGVkJyB8fCBzID09PSAnZXJyb3InO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCBmaW5hbFN0YXRlOiBzdHJpbmcgPSBzdG9yZS5zdGVwcy5zc2hDb25uZWN0aW9uLnN0YXRlO1xuICAgICAgICAgICAgaWYgKGZpbmFsU3RhdGUgPT09ICdlcnJvcicpIHtcbiAgICAgICAgICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIGtpbmQ6ICdzc2gtZmFpbGVkJyxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IHN0b3JlLnN0ZXBzLnNzaENvbm5lY3Rpb24uZXJyb3IgPz8gJ3NzaCBmYWlsZWQnLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnc3NoLWNvbm5lY3RlZCd9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBkaXNwYXRjaCh7a2luZDogJ3NzaC1mYWlsZWQnLCBlcnJvcjogZXJyTXNnKGVycil9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGN1cnIucGhhc2UgPT09ICdjb25uZWN0aW5nLWRiJykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY3R4LmRiID0gKGF3YWl0IGNvbm5lY3REQihzdG9yZSkpID8/IG51bGw7XG4gICAgICAgICAgICBhd2FpdCB3aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzOiBzdHJpbmcgPSBzdG9yZS5zdGVwcy5kYXRhYmFzZUNvbm5lY3Rpb24uc3RhdGU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHMgPT09ICdjb25uZWN0ZWQnIHx8IHMgPT09ICdlcnJvcic7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnN0IGRiU3RhdGU6IHN0cmluZyA9IHN0b3JlLnN0ZXBzLmRhdGFiYXNlQ29ubmVjdGlvbi5zdGF0ZTtcbiAgICAgICAgICAgIGlmIChkYlN0YXRlID09PSAnZXJyb3InIHx8IGN0eC5kYiA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAga2luZDogJ2RiLWZhaWxlZCcsXG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiBzdG9yZS5zdGVwcy5kYXRhYmFzZUNvbm5lY3Rpb24uZXJyb3IgPz8gJ2RiIGZhaWxlZCcsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGlzcGF0Y2goe2tpbmQ6ICdkYi1jb25uZWN0ZWQnfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgZGlzcGF0Y2goe2tpbmQ6ICdkYi1mYWlsZWQnLCBlcnJvcjogZXJyTXNnKGVycil9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGN1cnIucGhhc2UgPT09ICdpbnRyb3NwZWN0aW5nJykge1xuICAgICAgICBpZiAoY3R4LmRiID09PSBudWxsKSB7XG4gICAgICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAga2luZDogJ2ludHJvc3BlY3Rpb24tZmFpbGVkJyxcbiAgICAgICAgICAgICAgICBlcnJvcjogJ25vIGRiIGNvbm5lY3Rpb24nLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHVzZUpzb25QYXRoID0gc3RvcmUub3V0cHV0T3B0aW9ucy51c2VJbnRyb3NwZWN0aW9uSnNvblBhdGg7XG4gICAgICAgICAgICBpZiAodXNlSnNvblBhdGggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBydW5JbkFjdGlvbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHN0b3JlLnN0ZXBzLmludHJvc3BlY3Rpb24uc3RhdGUgPSAnZmV0Y2hpbmcnO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxvYWRlZCA9IGF3YWl0IGxvYWRJbnRyb3NwZWN0aW9uRnJvbUZpbGUoXG4gICAgICAgICAgICAgICAgICAgIHVzZUpzb25QYXRoLFxuICAgICAgICAgICAgICAgICAgICBjdHguZGIucG9vbCxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGlmICghbG9hZGVkLm9rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJ1bkluQWN0aW9uKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JlLnN0ZXBzLmludHJvc3BlY3Rpb24uc3RhdGUgPSAnZXJyb3InO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmUuc3RlcHMuaW50cm9zcGVjdGlvbi5lcnJvciA9IGxvYWRlZC5lcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAga2luZDogJ2ludHJvc3BlY3Rpb24tZmFpbGVkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBsb2FkZWQuZXJyb3IubWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcG9wdWxhdGVJbnRyb3NwZWN0aW9uQ291bnRzKHN0b3JlLCBsb2FkZWQucmVzdWx0KTtcbiAgICAgICAgICAgICAgICBydW5JbkFjdGlvbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHN0b3JlLnN0ZXBzLmludHJvc3BlY3Rpb24uc3RhdGUgPSAnZG9uZSc7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY3R4LmludHJvc3BlY3Rpb24gPSBsb2FkZWQucmVzdWx0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjdHguaW50cm9zcGVjdGlvbiA9IGF3YWl0IGFzc2VtYmxlRGF0YWJhc2UoY3R4LmRiLnBvb2wsIHN0b3JlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKERCQ1RYX0RFVikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHtkYXRhYmFzZUludHJvc3BlY3Rpb25TY2hlbWF9ID1cbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgaW1wb3J0KCdAZGJjdHgvY29yZS9zY2hlbWFzL2ludHJvc3BlY3Rpb24nKTtcbiAgICAgICAgICAgICAgICBkYXRhYmFzZUludHJvc3BlY3Rpb25TY2hlbWEucGFyc2UoY3R4LmludHJvc3BlY3Rpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGlzcGF0Y2goe2tpbmQ6ICdpbnRyb3NwZWN0aW9uLWxvYWRlZCd9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBkaXNwYXRjaCh7a2luZDogJ2ludHJvc3BlY3Rpb24tZmFpbGVkJywgZXJyb3I6IGVyck1zZyhlcnIpfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjdXJyLnBoYXNlID09PSAnb3V0cHV0LWpzb24nKSB7XG4gICAgICAgIGNvbnN0IG91dHB1dFBhdGggPSBjdXJyLm91dHB1dEpTT05QYXRoO1xuICAgICAgICBpZiAob3V0cHV0UGF0aCA9PT0gbnVsbCB8fCBjdHguaW50cm9zcGVjdGlvbiA9PT0gbnVsbCkge1xuICAgICAgICAgICAgZGlzcGF0Y2goe2tpbmQ6ICdvdXRwdXQtanNvbi1ub3QtcmVxdWVzdGVkJ30pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCByZWNvdmVyQXRvbWljV3JpdGUob3V0cHV0UGF0aCk7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgZXhpc3RzU3luYyhvdXRwdXRQYXRoKSAmJlxuICAgICAgICAgICAgICAgICFzdG9yZS5vdXRwdXRPcHRpb25zLmFsbG93SW50cm9zcGVjdGlvbkpzb25PdmVyd3JpdGVcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJ1bkluQWN0aW9uKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3RvcmUuc3RlcHMub3V0cHV0SnNvbi5zdGF0ZSA9ICdwcm9tcHRpbmctb3ZlcndyaXRlJztcbiAgICAgICAgICAgICAgICAgICAgc3RvcmUuc3RlcHMub3V0cHV0SnNvbi5wYXRoID0gb3V0cHV0UGF0aDtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBhd2FpdCB3aGVuKCgpID0+IHN0b3JlLnN0ZXBzLm91dHB1dEpzb24uY29uZmlybWVkICE9PSBudWxsKTtcbiAgICAgICAgICAgICAgICBpZiAoIXN0b3JlLnN0ZXBzLm91dHB1dEpzb24uY29uZmlybWVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnb3V0cHV0LWpzb24tc2tpcHBlZCd9KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJ1bkluQWN0aW9uKCgpID0+IHtcbiAgICAgICAgICAgICAgICBzdG9yZS5zdGVwcy5vdXRwdXRKc29uLnN0YXRlID0gJ3dyaXRpbmcnO1xuICAgICAgICAgICAgICAgIHN0b3JlLnN0ZXBzLm91dHB1dEpzb24ucGF0aCA9IG91dHB1dFBhdGg7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGF3YWl0IGF0b21pY1dyaXRlRmlsZShcbiAgICAgICAgICAgICAgICBvdXRwdXRQYXRoLFxuICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGN0eC5pbnRyb3NwZWN0aW9uLCBudWxsLCAyKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBydW5JbkFjdGlvbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RvcmUuc3RlcHMub3V0cHV0SnNvbi5zdGF0ZSA9ICdkb25lJztcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZGlzcGF0Y2goe2tpbmQ6ICdvdXRwdXQtanNvbi13cml0dGVuJ30pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHJ1bkluQWN0aW9uKCgpID0+IHtcbiAgICAgICAgICAgICAgICBzdG9yZS5zdGVwcy5vdXRwdXRKc29uLnN0YXRlID0gJ2Vycm9yJztcbiAgICAgICAgICAgICAgICBzdG9yZS5zdGVwcy5vdXRwdXRKc29uLmVycm9yID0gZXJyTXNnKGVycik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnb3V0cHV0LWpzb24tZmFpbGVkJywgZXJyb3I6IGVyck1zZyhlcnIpfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjdXJyLnBoYXNlID09PSAnY3JlYXRpbmctc2Vzc2lvbicpIHtcbiAgICAgICAgaWYgKGN0eC5kYiA9PT0gbnVsbCB8fCBjdHguaW50cm9zcGVjdGlvbiA9PT0gbnVsbCkge1xuICAgICAgICAgICAgZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIGtpbmQ6ICdzZXNzaW9uLWZhaWxlZCcsXG4gICAgICAgICAgICAgICAgZXJyb3I6ICdubyBkYiBvciBpbnRyb3NwZWN0aW9uIGluIGNvbnRleHQnLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbmZpZyA9IGF3YWl0IHJlYWRDb25maWcoKTtcbiAgICAgICAgICAgIGNvbnN0IHNlc3Npb25JZCA9IGF3YWl0IGNyZWF0ZVNlc3Npb24oXG4gICAgICAgICAgICAgICAgY3R4LmRiLnBvb2wsXG4gICAgICAgICAgICAgICAgY3R4LmludHJvc3BlY3Rpb24sXG4gICAgICAgICAgICAgICAgc3RvcmUsXG4gICAgICAgICAgICAgICAgY29uZmlnLnRva2VuID8/IG51bGwsXG4gICAgICAgICAgICAgICAgY29uZmlnLmRldmljZV9pZCxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIFJlLWF1dGggZmFzdC1wYXRoOiBpZiBleGlzdGluZyBjb25maWcgdG9rZW4gaXMgc3RpbGwgdmFsaWQsXG4gICAgICAgICAgICAvLyBza2lwIHRoZSBicm93c2VyLWF1dGggaGFuZHNoYWtlIGVudGlyZWx5LlxuICAgICAgICAgICAgaWYgKGNvbmZpZy50b2tlbikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGNvbm5lY3RBY2NvdW50KGNvbmZpZy50b2tlbiwgc3RvcmUpO1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBjaGVja0JpbGxpbmcoXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25maWcudG9rZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBidWlsZFNlc3Npb25VUkwoc2Vzc2lvbklkKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JlLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5Db250aW51ZSA9IGF3YWl0IGNoZWNrR2F0ZShjb25maWcudG9rZW4sIHN0b3JlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjYW5Db250aW51ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGF0Y2goe2tpbmQ6ICdhdXRoLW5vdC1uZWVkZWQnfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gU2luZ2xlIGRpc3BhdGNoIGNhcnJ5aW5nIGJvdGggc2Vzc2lvbklkIGFuZCB0b2tlbi5cbiAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWRzIHRyYW5zaXRpb25pbmcgdGhyb3VnaCBhd2FpdGluZy1hdXRob3JpemF0aW9uLFxuICAgICAgICAgICAgICAgICAgICAvLyB3aGljaCB3b3VsZCByYWNlLWZpcmUgd2FpdEZvckF1dGhvcml6YXRpb24gYW5kIHN0b21wXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBhbHJlYWR5LSdjb25uZWN0ZWQnIGFjY291bnQgc3RhdGUgYmFjayB0byAnd2FpdGluZycuXG4gICAgICAgICAgICAgICAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtpbmQ6ICdmYXN0LXBhdGgtY29tcGxldGVkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiBjb25maWcudG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIGVyciBpbnN0YW5jZW9mIFRSUENDbGllbnRFcnJvciAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKGVyci5kYXRhPy5jb2RlID09PSAnVU5BVVRIT1JJWkVEJyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVyci5kYXRhPy5jb2RlID09PSAnTk9UX0ZPVU5EJylcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBmbHVzaENvbmZpZygpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkaXNwYXRjaCh7a2luZDogJ3Nlc3Npb24tY3JlYXRlZCcsIHNlc3Npb25JZH0pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnc2Vzc2lvbi1mYWlsZWQnLCBlcnJvcjogZXJyTXNnKGVycil9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGN1cnIucGhhc2UgPT09ICdhd2FpdGluZy1hdXRob3JpemF0aW9uJykge1xuICAgICAgICBpZiAoY3Vyci5zZXNzaW9uSWQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnYXV0aC1mYWlsZWQnLCBlcnJvcjogJ25vIHNlc3Npb25JZCBpbiBzdGF0ZSd9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgd2FpdEZvckF1dGhvcml6YXRpb24oY3Vyci5zZXNzaW9uSWQsIHN0b3JlKTtcbiAgICAgICAgICAgIGNvbnN0IGZyZXNoVG9rZW4gPSAoYXdhaXQgcmVhZENvbmZpZygpKS50b2tlbjtcbiAgICAgICAgICAgIGlmICghZnJlc2hUb2tlbikge1xuICAgICAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnYXV0aC1mYWlsZWQnLCBlcnJvcjogJ25vIHRva2VuIGFmdGVyIGF1dGgnfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXdhaXQgY2hlY2tCaWxsaW5nKFxuICAgICAgICAgICAgICAgIGZyZXNoVG9rZW4sXG4gICAgICAgICAgICAgICAgYnVpbGRTZXNzaW9uVVJMKGN1cnIuc2Vzc2lvbklkKSxcbiAgICAgICAgICAgICAgICBzdG9yZSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBjYW5Db250aW51ZSA9IGF3YWl0IGNoZWNrR2F0ZShmcmVzaFRva2VuLCBzdG9yZSk7XG4gICAgICAgICAgICBpZiAoIWNhbkNvbnRpbnVlKSB7XG4gICAgICAgICAgICAgICAgZGlzcGF0Y2goe2tpbmQ6ICdhdXRoLWZhaWxlZCcsIGVycm9yOiAnZ2F0ZSBibG9ja2VkJ30pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnYXV0aC1jb25maXJtZWQnLCB0b2tlbjogZnJlc2hUb2tlbn0pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnYXV0aC1mYWlsZWQnLCBlcnJvcjogZXJyTXNnKGVycil9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGN1cnIucGhhc2UgPT09ICdhd2FpdGluZy1leHBsYW5hdGlvbicpIHtcbiAgICAgICAgaWYgKGN1cnIuZXhwbGFuYXRpb24gIT09IG51bGwpIHtcbiAgICAgICAgICAgIGN0eC5leHBsYW5hdGlvbiA9IGN1cnIuZXhwbGFuYXRpb247XG4gICAgICAgICAgICBydW5JbkFjdGlvbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RvcmUuc3RlcHMudXNlckV4cGxhbmF0aW9uLnN0YXRlID0gJ2RvbmUnO1xuICAgICAgICAgICAgICAgIHN0b3JlLnN0ZXBzLnVzZXJFeHBsYW5hdGlvbi52YWx1ZSA9IGN1cnIuZXhwbGFuYXRpb247XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICBraW5kOiAnZXhwbGFuYXRpb24tZ2l2ZW4nLFxuICAgICAgICAgICAgICAgIHZhbHVlOiBjdXJyLmV4cGxhbmF0aW9uLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgcnVuSW5BY3Rpb24oKCkgPT4ge1xuICAgICAgICAgICAgc3RvcmUuc3RlcHMudXNlckV4cGxhbmF0aW9uLnN0YXRlID0gJ3Byb21wdGluZyc7XG4gICAgICAgIH0pO1xuICAgICAgICBhd2FpdCB3aGVuKCgpID0+IHN0b3JlLnN0ZXBzLnVzZXJFeHBsYW5hdGlvbi5zdGF0ZSA9PT0gJ2RvbmUnKTtcbiAgICAgICAgY29uc3QgdiA9IHN0b3JlLnN0ZXBzLnVzZXJFeHBsYW5hdGlvbi52YWx1ZSA/PyAnJztcbiAgICAgICAgY3R4LmV4cGxhbmF0aW9uID0gdjtcbiAgICAgICAgZGlzcGF0Y2goe2tpbmQ6ICdleHBsYW5hdGlvbi1naXZlbicsIHZhbHVlOiB2fSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoY3Vyci5waGFzZSA9PT0gJ3ByZWZsaWdodC1jaGVja2luZycpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgY3R4LmRiID09PSBudWxsIHx8XG4gICAgICAgICAgICBjdHguaW50cm9zcGVjdGlvbiA9PT0gbnVsbCB8fFxuICAgICAgICAgICAgY3Vyci5hdXRoVG9rZW4gPT09IG51bGwgfHxcbiAgICAgICAgICAgIGN1cnIuc2Vzc2lvbklkID09PSBudWxsXG4gICAgICAgICkge1xuICAgICAgICAgICAgZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIGtpbmQ6ICdpbmdlc3QtZmFpbGVkJyxcbiAgICAgICAgICAgICAgICBlcnJvcjogJ2NvbnRleHQgbm90IHJlYWR5IGZvciBwcmVmbGlnaHQnLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGN0eC5hdXRoZWQgPSBjcmVhdGVBdXRoZW50aWNhdGVkVFJQQ0NsaWVudCgoKSA9PlxuICAgICAgICAgICAgICAgIFByb21pc2UucmVzb2x2ZShjdXJyLmF1dGhUb2tlbiEpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGV4cGxhbmF0aW9uID0gY3R4LmV4cGxhbmF0aW9uID8/IGN1cnIuZXhwbGFuYXRpb247XG4gICAgICAgICAgICBpZiAoZXhwbGFuYXRpb24gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjdHguaW50cm9zcGVjdGlvbi51c2VyRXhwbGFuYXRpb24gPSBleHBsYW5hdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHBsYW5uZXJTdGF0cyA9IGF3YWl0IGZldGNoUHVibGljUGxhbm5lclN0YXRpc3RpY3MoXG4gICAgICAgICAgICAgICAgY3R4LmRiLnBvb2wsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgaW50cm9zcGVjdGlvbkhhc2ggPSBjb21wdXRlU2NoZW1hSGFzaChjdHguaW50cm9zcGVjdGlvbik7XG4gICAgICAgICAgICBjb25zdCBjaGVja0hpdCA9XG4gICAgICAgICAgICAgICAgYXdhaXQgY3R4LmF1dGhlZC5yZXZpc2lvbnMuY2hlY2tJbnRyb3NwZWN0aW9uLm11dGF0ZSh7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogY3Vyci5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIGludHJvc3BlY3Rpb25IYXNoLFxuICAgICAgICAgICAgICAgICAgICBzeXN0ZW1JZGVudGlmaWVyOlxuICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmludHJvc3BlY3Rpb24uaWRlbnRpZmllci5zeXN0ZW1faWRlbnRpZmllcixcbiAgICAgICAgICAgICAgICAgICAgZGF0YWJhc2VPSUQ6IFN0cmluZyhcbiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5pbnRyb3NwZWN0aW9uLmlkZW50aWZpZXIuZGF0YWJhc2Vfb2lkLFxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICBwbGFubmVyU3RhdGlzdGljczoge3JlbGF0aW9uczogcGxhbm5lclN0YXRzfSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChjaGVja0hpdCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJ1bkluQWN0aW9uKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3RvcmUubGFuZGluZ1VSTCA9IGNoZWNrSGl0LmxhbmRpbmdVUkw7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAga2lja1Bvc3RJbnRyb3NwZWN0aW9uUG9sbChcbiAgICAgICAgICAgICAgICAgICAgY3R4LFxuICAgICAgICAgICAgICAgICAgICBjaGVja0hpdC5wb3N0SW50cm9zcGVjdGlvbkpvYklkLFxuICAgICAgICAgICAgICAgICAgICBzdG9yZSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAga2luZDogJ2NoZWNrLWludHJvc3BlY3Rpb24taGl0JyxcbiAgICAgICAgICAgICAgICAgICAgcmV2aXNpb25JZDogY2hlY2tIaXQucmV2aXNpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgc2FtcGxlc0V4aXN0OiBjaGVja0hpdC5zYW1wbGVzRXhpc3QsXG4gICAgICAgICAgICAgICAgICAgIHRhYmxlc05lZWRpbmdTYW1wbGVzOiBjaGVja0hpdC50YWJsZXNOZWVkaW5nU2FtcGxlcyxcbiAgICAgICAgICAgICAgICAgICAgcG9zdEludHJvc3BlY3Rpb25Kb2JJZDogY2hlY2tIaXQucG9zdEludHJvc3BlY3Rpb25Kb2JJZCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkaXNwYXRjaCh7a2luZDogJ2NoZWNrLWludHJvc3BlY3Rpb24tbWlzcyd9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBkaXNwYXRjaEluZ2VzdEZhaWxlZChlcnIsIGRpc3BhdGNoLCBzdG9yZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjdXJyLnBoYXNlID09PSAnaW5nZXN0aW5nLWludHJvc3BlY3Rpb24nKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGN0eC5hdXRoZWQgPT09IG51bGwgfHxcbiAgICAgICAgICAgIGN0eC5pbnRyb3NwZWN0aW9uID09PSBudWxsIHx8XG4gICAgICAgICAgICBjdXJyLnNlc3Npb25JZCA9PT0gbnVsbCB8fFxuICAgICAgICAgICAgY3R4LmRiID09PSBudWxsXG4gICAgICAgICkge1xuICAgICAgICAgICAgZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIGtpbmQ6ICdpbmdlc3QtZmFpbGVkJyxcbiAgICAgICAgICAgICAgICBlcnJvcjogJ2NvbnRleHQgbm90IHJlYWR5IGZvciBpbmdlc3QnLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJ1bkluQWN0aW9uKCgpID0+IHtcbiAgICAgICAgICAgICAgICBzdG9yZS5zdGVwcy5pbmdlc3Rpb24uaW50cm9zcGVjdGlvbi5zdGF0ZSA9ICd1cGxvYWRpbmcnO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCBwbGFubmVyU3RhdHMgPSBhd2FpdCBmZXRjaFB1YmxpY1BsYW5uZXJTdGF0aXN0aWNzKFxuICAgICAgICAgICAgICAgIGN0eC5kYi5wb29sLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGluZ2VzdCA9XG4gICAgICAgICAgICAgICAgYXdhaXQgY3R4LmF1dGhlZC5yZXZpc2lvbnMuaW5nZXN0SW50cm9zcGVjdGlvbi5tdXRhdGUoe1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uSWQ6IGN1cnIuc2Vzc2lvbklkLFxuICAgICAgICAgICAgICAgICAgICBpbnRyb3NwZWN0aW9uOiBjdHguaW50cm9zcGVjdGlvbixcbiAgICAgICAgICAgICAgICAgICAgcGxhbm5lclN0YXRpc3RpY3M6IHtyZWxhdGlvbnM6IHBsYW5uZXJTdGF0c30sXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBydW5JbkFjdGlvbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RvcmUubGFuZGluZ1VSTCA9IGluZ2VzdC5sYW5kaW5nVVJMO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBraWNrUG9zdEludHJvc3BlY3Rpb25Qb2xsKFxuICAgICAgICAgICAgICAgIGN0eCxcbiAgICAgICAgICAgICAgICBpbmdlc3QucG9zdEludHJvc3BlY3Rpb25Kb2JJZCxcbiAgICAgICAgICAgICAgICBzdG9yZSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAga2luZDogJ2ludHJvc3BlY3Rpb24taW5nZXN0ZWQnLFxuICAgICAgICAgICAgICAgIHJldmlzaW9uSWQ6IGluZ2VzdC5yZXZpc2lvbklkLFxuICAgICAgICAgICAgICAgIHNhbXBsZXNFeGlzdDogaW5nZXN0LnNhbXBsZXNFeGlzdCxcbiAgICAgICAgICAgICAgICB0YWJsZXNOZWVkaW5nU2FtcGxlczogaW5nZXN0LnRhYmxlc05lZWRpbmdTYW1wbGVzLFxuICAgICAgICAgICAgICAgIHBvc3RJbnRyb3NwZWN0aW9uSm9iSWQ6IGluZ2VzdC5wb3N0SW50cm9zcGVjdGlvbkpvYklkLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgZGlzcGF0Y2hJbmdlc3RGYWlsZWQoZXJyLCBkaXNwYXRjaCwgc3RvcmUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoY3Vyci5waGFzZSA9PT0gJ3NhbXBsaW5nLW1hc2stcmVzb2x2aW5nJykge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBjdHguYXV0aGVkID09PSBudWxsIHx8XG4gICAgICAgICAgICBjdXJyLnJldmlzaW9uSWQgPT09IG51bGwgfHxcbiAgICAgICAgICAgIGN0eC5pbnRyb3NwZWN0aW9uID09PSBudWxsXG4gICAgICAgICkge1xuICAgICAgICAgICAgZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIGtpbmQ6ICdtYXNrLWZldGNoLWZhaWxlZCcsXG4gICAgICAgICAgICAgICAgZXJyb3I6ICdjb250ZXh0IG5vdCByZWFkeSBmb3IgbWFzayByZXNvbHV0aW9uJyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBmaWxlTWFza1BhdGggPSBjdXJyLmZpbGVNYXNrUGF0aDtcbiAgICAgICAgICAgIGlmIChmaWxlTWFza1BhdGggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXNrID0gYXdhaXQgbG9hZFNlbnNpdGl2ZU1hc2soZmlsZU1hc2tQYXRoKTtcbiAgICAgICAgICAgICAgICBkaXNwYXRjaCh7a2luZDogJ21hc2stbG9hZGVkJywgbWFza30pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFNlcnZlci1tYW5hZ2VkIG1hc2s6IHdhaXQgZm9yIHBvc3QtaW50cm9zcGVjdGlvbiB0byBmaW5pc2guXG4gICAgICAgICAgICBpZiAoY3R4LnBvc3RJbnRyb3NwZWN0aW9uUG9sbCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IGN0eC5wb3N0SW50cm9zcGVjdGlvblBvbGw7XG4gICAgICAgICAgICAgICAgY3R4LnBvc3RJbnRyb3NwZWN0aW9uUG9sbCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBBZnRlciB0aGUgYXdhaXQsIHN1Yi1zdGF0dXMgcmVmbGVjdHMgcG9zdC1pbnRyb3NwZWN0aW9uIHN0YXRlLlxuICAgICAgICAgICAgLy8gVGhlIHJlZHVjZXIncyBwcm9qZWN0aW9uIHdvbid0IGhhdmUgcmUtZmlyZWQgZHJpdmVTaWRlIG9uIGl0cyBvd25cbiAgICAgICAgICAgIC8vIChzdWItc3RhdHVzIG9ubHkpLiBJbnNwZWN0IHN0b3JlIGRpcmVjdGx5LlxuICAgICAgICAgICAgaWYgKHN0b3JlLnN0ZXBzLmluZ2VzdGlvbi5wb3N0SW50cm9zcGVjdGlvbi5zdGF0ZSA9PT0gJ2Vycm9yJykge1xuICAgICAgICAgICAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAga2luZDogJ21hc2stZmV0Y2gtZmFpbGVkJyxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3I6ICdwb3N0LWludHJvc3BlY3Rpb24gZW5yaWNobWVudCBmYWlsZWQg4oCUIHNlbnNpdGl2ZSBtYXNrIHVuYXZhaWxhYmxlOyByZWZ1c2luZyB0byBzYW1wbGUnLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGN0eC5hdXRoZWQucmV2aXNpb25zLmdldFNlbnNpdGl2ZU1hc2sucXVlcnkoe1xuICAgICAgICAgICAgICAgIHJldmlzaW9uSWQ6IGN1cnIucmV2aXNpb25JZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCFyZXMucmVhZHkpIHtcbiAgICAgICAgICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIGtpbmQ6ICdtYXNrLWZldGNoLWZhaWxlZCcsXG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiAnc2VydmVyIHJlcG9ydGVkIHNlbnNpdGl2ZSBtYXNrIG5vdCByZWFkeSBhZnRlciBwb3N0LWludHJvc3BlY3Rpb24gY29tcGxldGlvbjsgcmVmdXNpbmcgdG8gc2FtcGxlJyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkaXNwYXRjaCh7a2luZDogJ21hc2stbG9hZGVkJywgbWFzazogcmVzLm1hc2t9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBkaXNwYXRjaCh7a2luZDogJ21hc2stZmV0Y2gtZmFpbGVkJywgZXJyb3I6IGVyck1zZyhlcnIpfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjdXJyLnBoYXNlID09PSAnc2FtcGxpbmcnKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGN0eC5kYiA9PT0gbnVsbCB8fFxuICAgICAgICAgICAgY3R4LmludHJvc3BlY3Rpb24gPT09IG51bGwgfHxcbiAgICAgICAgICAgIGN1cnIuc2FtcGxpbmcubWFzayA9PT0gbnVsbFxuICAgICAgICApIHtcbiAgICAgICAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICBraW5kOiAnc2FtcGxpbmctZmFpbGVkJyxcbiAgICAgICAgICAgICAgICBlcnJvcjogJ2NvbnRleHQgbm90IHJlYWR5IGZvciBzYW1wbGluZycsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgbWFzazogVFNlbnNpdGl2ZU1hc2sgPSBjdXJyLnNhbXBsaW5nLm1hc2s7XG4gICAgICAgICAgICBjb25zdCBzYW1wbGVGaWxlSW5kZXg6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgICAgICAgIGNvbnN0IG91dHB1dERpciA9IGN1cnIub3V0cHV0U2FtcGxlc0RpcjtcbiAgICAgICAgICAgIGlmIChvdXRwdXREaXIgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWFkeSA9IGF3YWl0IHByZXBhcmVPdXRwdXREaXIoXG4gICAgICAgICAgICAgICAgICAgIG91dHB1dERpcixcbiAgICAgICAgICAgICAgICAgICAgc3RvcmUub3V0cHV0T3B0aW9ucy5hbGxvd1NhbXBsZU92ZXJ3cml0ZSxcbiAgICAgICAgICAgICAgICAgICAgc3RvcmUsXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBpZiAoIXJlYWR5KSB7XG4gICAgICAgICAgICAgICAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtpbmQ6ICdzYW1wbGluZy1mYWlsZWQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6ICdvdXRwdXQgZGlyIG5vdCByZWFkeScsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRmlsdGVyIHRoZSBwZXItdGFibGUgc2FtcGxpbmcgbG9vcCB0byBvbmx5IHRoZSB0YWJsZXMgdGhlXG4gICAgICAgICAgICAvLyBzZXJ2ZXIgZmxhZ2dlZCBhcyBuZWVkaW5nIGZyZXNoIHNhbXBsZXMuIE51bGwgPSBwcmUtaGFuZHNoYWtlXG4gICAgICAgICAgICAvLyBzZW50aW5lbDsgdHJlYXQgYXMgXCJhbGwgdGFibGVzXCIgZm9yIHNhZmV0eS5cbiAgICAgICAgICAgIGNvbnN0IHRhYmxlRmlsdGVyOiBSZWFkb25seVNldDxzdHJpbmc+IHwgdW5kZWZpbmVkID1cbiAgICAgICAgICAgICAgICBjdXJyLnRhYmxlc05lZWRpbmdTYW1wbGVzID09PSBudWxsXG4gICAgICAgICAgICAgICAgICAgID8gdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgICAgIDogbmV3IFNldChjdXJyLnRhYmxlc05lZWRpbmdTYW1wbGVzKTtcbiAgICAgICAgICAgIGZvciBhd2FpdCAoY29uc3QgZXZlbnQgb2YgcnVuU2FtcGxpbmcoXG4gICAgICAgICAgICAgICAgY3R4LmRiLnBvb2wsXG4gICAgICAgICAgICAgICAgY3R4LmludHJvc3BlY3Rpb24sXG4gICAgICAgICAgICAgICAgc3RvcmUsXG4gICAgICAgICAgICAgICAgbWFzayxcbiAgICAgICAgICAgICAgICB0YWJsZUZpbHRlcixcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAgICAgICBpZiAob3V0cHV0RGlyICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHBlcnNpc3RUYWJsZVNhbXBsZXNUb0RpcihcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dERpcixcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlRmlsZUluZGV4LFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkaXNwYXRjaCh7a2luZDogJ3NhbXBsZS10YWJsZS15aWVsZGVkJywgZXZlbnR9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnc2FtcGxpbmctY29tcGxldGVkJ30pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnc2FtcGxpbmctZmFpbGVkJywgZXJyb3I6IGVyck1zZyhlcnIpfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjdXJyLnBoYXNlID09PSAndXBsb2FkaW5nLXNhbXBsZXMnKSB7XG4gICAgICAgIGlmIChjdHguYXV0aGVkID09PSBudWxsIHx8IGN1cnIucmV2aXNpb25JZCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIGtpbmQ6ICdzYW1wbGVzLXVwbG9hZC1mYWlsZWQnLFxuICAgICAgICAgICAgICAgIGVycm9yOiAnY29udGV4dCBub3QgcmVhZHkgZm9yIHVwbG9hZCcsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qgc2FtcGxlcyA9IGN1cnIuc2FtcGxpbmcuY29sbGVjdGVkO1xuICAgICAgICAgICAgaWYgKHNhbXBsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcnVuSW5BY3Rpb24oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzdG9yZS5zdGVwcy5pbmdlc3Rpb24uc2FtcGxlcy5zdGF0ZSA9ICdkb25lJztcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBkaXNwYXRjaCh7a2luZDogJ3NhbXBsZXMtdXBsb2FkLW5vdC1uZWVkZWQnfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc2FtcGxlSW5wdXRzID0gc2FtcGxlcy5tYXAoKGV2ZW50KSA9PiAoe1xuICAgICAgICAgICAgICAgIHRhYmxlTmFtZTogZXZlbnQudGFibGVOYW1lLFxuICAgICAgICAgICAgICAgIGNvbHVtbnM6IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMoZXZlbnQuc2FtcGxlcy5jb2x1bW5zKS5tYXAoKFtjb2wsIHNdKSA9PiBbXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2wsXG4gICAgICAgICAgICAgICAgICAgICAgICBbLi4ucy52YWx1ZXNdLFxuICAgICAgICAgICAgICAgICAgICBdKSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgY29uc3QgQ0hVTktfU0laRSA9IDI1O1xuICAgICAgICAgICAgcnVuSW5BY3Rpb24oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHN0b3JlLnN0ZXBzLmluZ2VzdGlvbi5zYW1wbGVzLnN0YXRlID0gJ3VwbG9hZGluZyc7XG4gICAgICAgICAgICAgICAgc3RvcmUuc3RlcHMuaW5nZXN0aW9uLnNhbXBsZXMudG90YWxUYWJsZXMgPSBzYW1wbGVJbnB1dHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHN0b3JlLnN0ZXBzLmluZ2VzdGlvbi5zYW1wbGVzLnVwbG9hZGVkVGFibGVzID0gMDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uc3QgY2h1bmtzID0gQXJyYXkuZnJvbShcbiAgICAgICAgICAgICAgICB7bGVuZ3RoOiBNYXRoLmNlaWwoc2FtcGxlSW5wdXRzLmxlbmd0aCAvIENIVU5LX1NJWkUpfSxcbiAgICAgICAgICAgICAgICAoXywgaSkgPT5cbiAgICAgICAgICAgICAgICAgICAgc2FtcGxlSW5wdXRzLnNsaWNlKGkgKiBDSFVOS19TSVpFLCAoaSArIDEpICogQ0hVTktfU0laRSksXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaHVua3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjaHVuayA9IGNodW5rc1tpXTtcbiAgICAgICAgICAgICAgICBhd2FpdCBjdHguYXV0aGVkLnJldmlzaW9ucy5pbmdlc3RTYW1wbGVzLm11dGF0ZSh7XG4gICAgICAgICAgICAgICAgICAgIHJldmlzaW9uSWQ6IGN1cnIucmV2aXNpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgc2FtcGxlczogY2h1bmssXG4gICAgICAgICAgICAgICAgICAgIGNodW5rSW5kZXg6IGksXG4gICAgICAgICAgICAgICAgICAgIGNodW5rVG90YWw6IGNodW5rcy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcnVuSW5BY3Rpb24oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzdG9yZS5zdGVwcy5pbmdlc3Rpb24uc2FtcGxlcy51cGxvYWRlZFRhYmxlcyArPVxuICAgICAgICAgICAgICAgICAgICAgICAgY2h1bmsubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAga2luZDogJ3NhbXBsZS1jaHVuay11cGxvYWRlZCcsXG4gICAgICAgICAgICAgICAgICAgIGNodW5rU2l6ZTogY2h1bmsubGVuZ3RoLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcnVuSW5BY3Rpb24oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHN0b3JlLnN0ZXBzLmluZ2VzdGlvbi5zYW1wbGVzLnN0YXRlID0gJ2RvbmUnO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICBgaW5nZXN0ZWQgJHtzYW1wbGVJbnB1dHMubGVuZ3RofSBzYW1wbGUgdGFibGVzIGluICR7Y2h1bmtzLmxlbmd0aH0gY2h1bmsocylgLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnc2FtcGxlcy11cGxvYWQtY29tcGxldGVkJ30pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGRpc3BhdGNoKHtraW5kOiAnc2FtcGxlcy11cGxvYWQtZmFpbGVkJywgZXJyb3I6IGVyck1zZyhlcnIpfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjdXJyLnBoYXNlID09PSAnYXdhaXRpbmctcG9zdC1zYW1wbGluZycpIHtcbiAgICAgICAgaWYgKGN0eC5hdXRoZWQgPT09IG51bGwgfHwgY3Vyci5yZXZpc2lvbklkID09PSBudWxsKSB7XG4gICAgICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAga2luZDogJ3Bvc3Qtc2FtcGxpbmctZmFpbGVkJyxcbiAgICAgICAgICAgICAgICBlcnJvcjogJ2NvbnRleHQgbm90IHJlYWR5JyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBGaXJzdCBlbnN1cmUgcG9zdC1pbnRyb3NwZWN0aW9uIGZpbmlzaGVkIChmaWxlLW1hc2sgZmFzdCBwYXRoIG1heVxuICAgICAgICAgICAgLy8gaGF2ZSBza2lwcGVkIHRoZSBleHBsaWNpdCBhd2FpdCBlYXJsaWVyKS5cbiAgICAgICAgICAgIGlmIChjdHgucG9zdEludHJvc3BlY3Rpb25Qb2xsICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgY3R4LnBvc3RJbnRyb3NwZWN0aW9uUG9sbDtcbiAgICAgICAgICAgICAgICBjdHgucG9zdEludHJvc3BlY3Rpb25Qb2xsID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzdG9yZS5zdGVwcy5pbmdlc3Rpb24ucG9zdEludHJvc3BlY3Rpb24uc3RhdGUgPT09ICdlcnJvcicpIHtcbiAgICAgICAgICAgICAgICBydW5JbkFjdGlvbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHN0b3JlLnN0ZXBzLmluZ2VzdGlvbi5wb3N0U2FtcGxpbmcuc3RhdGUgPSAnZXJyb3InO1xuICAgICAgICAgICAgICAgICAgICBzdG9yZS5zdGVwcy5pbmdlc3Rpb24ucG9zdFNhbXBsaW5nLmVycm9yID1cbiAgICAgICAgICAgICAgICAgICAgICAgICdza2lwcGVkIOKAlCBwb3N0LWludHJvc3BlY3Rpb24gZW5yaWNobWVudCBmYWlsZWQnO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAga2luZDogJ3Bvc3Qtc2FtcGxpbmctZmFpbGVkJyxcbiAgICAgICAgICAgICAgICAgICAgZXJyb3I6ICdwb3N0LWludHJvc3BlY3Rpb24gZW5yaWNobWVudCBmYWlsZWQnLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IGRpc3BhdGNoQW5kU3RyZWFtUG9zdFNhbXBsaW5nKFxuICAgICAgICAgICAgICAgIGN0eC5hdXRoZWQsXG4gICAgICAgICAgICAgICAgY3Vyci5yZXZpc2lvbklkLFxuICAgICAgICAgICAgICAgIHN0b3JlLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChzdG9yZS5zdGVwcy5pbmdlc3Rpb24ucG9zdFNhbXBsaW5nLnN0YXRlID09PSAnZXJyb3InKSB7XG4gICAgICAgICAgICAgICAgZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICBraW5kOiAncG9zdC1zYW1wbGluZy1mYWlsZWQnLFxuICAgICAgICAgICAgICAgICAgICBlcnJvcjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JlLnN0ZXBzLmluZ2VzdGlvbi5wb3N0U2FtcGxpbmcuZXJyb3IgPz9cbiAgICAgICAgICAgICAgICAgICAgICAgICdwb3N0LXNhbXBsaW5nIGZhaWxlZCcsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGlzcGF0Y2goe2tpbmQ6ICdwb3N0LXNhbXBsaW5nLWNvbXBsZXRlZCd9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBkaXNwYXRjaCh7a2luZDogJ3Bvc3Qtc2FtcGxpbmctZmFpbGVkJywgZXJyb3I6IGVyck1zZyhlcnIpfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjdXJyLnBoYXNlID09PSAnZG9uZScgfHwgY3Vyci5waGFzZSA9PT0gJ2Vycm9yJykge1xuICAgICAgICBjbGVhbnVwKGN0eCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG59O1xuXG5jb25zdCBraWNrUG9zdEludHJvc3BlY3Rpb25Qb2xsID0gKFxuICAgIGN0eDogVEludGVycHJldGVyQ29udGV4dCxcbiAgICBqb2JJZDogc3RyaW5nIHwgbnVsbCxcbiAgICBzdG9yZTogVFN0b3JlLFxuKTogdm9pZCA9PiB7XG4gICAgcnVuSW5BY3Rpb24oKCkgPT4ge1xuICAgICAgICBpZiAoam9iSWQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHN0b3JlLnN0ZXBzLmluZ2VzdGlvbi5wb3N0SW50cm9zcGVjdGlvbi5zdGF0ZSA9ICdkb25lJztcbiAgICAgICAgICAgIHN0b3JlLnN0ZXBzLmluZ2VzdGlvbi5wb3N0SW50cm9zcGVjdGlvbi5yZXVzZWQgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3RvcmUuc3RlcHMuaW5nZXN0aW9uLnBvc3RJbnRyb3NwZWN0aW9uLmpvYklkID0gam9iSWQ7XG4gICAgICAgICAgICBpZiAoc3RvcmUuc3RlcHMuaW5nZXN0aW9uLnBvc3RJbnRyb3NwZWN0aW9uLnN0YXRlID09PSAnaWRsZScpIHtcbiAgICAgICAgICAgICAgICBzdG9yZS5zdGVwcy5pbmdlc3Rpb24ucG9zdEludHJvc3BlY3Rpb24uc3RhdGUgPSAncXVldWVkJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGlmIChqb2JJZCA9PT0gbnVsbCB8fCBjdHguYXV0aGVkID09PSBudWxsKSB7XG4gICAgICAgIGN0eC5wb3N0SW50cm9zcGVjdGlvblBvbGwgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjdHgucG9zdEludHJvc3BlY3Rpb25Qb2xsID0gc3RyZWFtUG9zdEludHJvc3BlY3Rpb24oXG4gICAgICAgIGN0eC5hdXRoZWQsXG4gICAgICAgIGpvYklkLFxuICAgICAgICBzdG9yZSxcbiAgICApLnRoZW4oXG4gICAgICAgICgpID0+IHt9LFxuICAgICAgICAoKSA9PiB7fSxcbiAgICApO1xufTtcblxuZXhwb3J0IGNvbnN0IGNsZWFudXAgPSAoY3R4OiBUSW50ZXJwcmV0ZXJDb250ZXh0KTogdm9pZCA9PiB7XG4gICAgaWYgKGN0eC5kYiAhPT0gbnVsbCkge1xuICAgICAgICBjdHguZGIuY2xlYW51cCgpO1xuICAgICAgICBjdHguZGIgPSBudWxsO1xuICAgIH1cbiAgICBpZiAoY3R4LmNsZWFudXBTU0ggIT09IG51bGwpIHtcbiAgICAgICAgY3R4LmNsZWFudXBTU0goKTtcbiAgICAgICAgY3R4LmNsZWFudXBTU0ggPSBudWxsO1xuICAgIH1cbn07XG4iXX0=