sonamu 0.9.3 → 0.9.5

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 (99) hide show
  1. package/dist/ai/providers/rtzr/utils.js +2 -2
  2. package/dist/api/config.d.ts +0 -8
  3. package/dist/api/config.d.ts.map +1 -1
  4. package/dist/api/config.js +1 -1
  5. package/dist/api/sonamu.d.ts +0 -1
  6. package/dist/api/sonamu.d.ts.map +1 -1
  7. package/dist/api/sonamu.js +2 -41
  8. package/dist/auth/audit-log/builders.d.ts +216 -0
  9. package/dist/auth/audit-log/builders.d.ts.map +1 -0
  10. package/dist/auth/audit-log/builders.js +307 -0
  11. package/dist/auth/audit-log/events.d.ts +143 -0
  12. package/dist/auth/audit-log/events.d.ts.map +1 -0
  13. package/dist/auth/audit-log/events.js +74 -0
  14. package/dist/auth/audit-log/plugin.d.ts +11 -0
  15. package/dist/auth/audit-log/plugin.d.ts.map +1 -0
  16. package/dist/auth/audit-log/plugin.js +427 -0
  17. package/dist/auth/audit-log-ingestor.d.ts +3 -3
  18. package/dist/auth/audit-log-ingestor.d.ts.map +1 -1
  19. package/dist/auth/audit-log-ingestor.js +44 -50
  20. package/dist/auth/index.d.ts +2 -0
  21. package/dist/auth/index.d.ts.map +1 -1
  22. package/dist/auth/index.js +4 -4
  23. package/dist/auth/plugins/entity-definitions/admin.d.ts +1 -1
  24. package/dist/auth/plugins/entity-definitions/admin.js +4 -4
  25. package/dist/auth/plugins/entity-definitions/audit-log.d.ts +2 -2
  26. package/dist/auth/plugins/entity-definitions/audit-log.js +3 -3
  27. package/dist/auth/plugins/wrappers/admin.d.ts +2 -2
  28. package/dist/auth/plugins/wrappers/sso.d.ts +1 -1
  29. package/dist/bin/fixture.d.ts.map +1 -1
  30. package/dist/bin/fixture.js +111 -1
  31. package/dist/database/_batch_update.d.ts +1 -1
  32. package/dist/database/_batch_update.js +2 -2
  33. package/dist/database/upsert-builder.js +4 -4
  34. package/dist/dict/sonamu-dictionary.js +2 -2
  35. package/dist/entity/entity-manager.d.ts +2 -2
  36. package/dist/entity/entity-manager.d.ts.map +1 -1
  37. package/dist/entity/entity-manager.js +14 -4
  38. package/dist/index.js +4 -3
  39. package/dist/migration/code-generation.d.ts.map +1 -1
  40. package/dist/migration/code-generation.js +2 -3
  41. package/dist/syncer/syncer.d.ts.map +1 -1
  42. package/dist/syncer/syncer.js +2 -9
  43. package/dist/template/implementations/entry-server.template.js +3 -2
  44. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  45. package/dist/template/implementations/generated.template.js +2 -1
  46. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
  47. package/dist/template/implementations/generated_sso.template.js +2 -1
  48. package/dist/template/implementations/queries.template.d.ts.map +1 -1
  49. package/dist/template/implementations/queries.template.js +3 -1
  50. package/dist/template/implementations/sd.template.js +3 -2
  51. package/dist/template/implementations/services.template.d.ts.map +1 -1
  52. package/dist/template/implementations/services.template.js +44 -7
  53. package/dist/template/zod-converter.d.ts.map +1 -1
  54. package/dist/template/zod-converter.js +2 -2
  55. package/dist/testing/data-explorer.d.ts.map +1 -1
  56. package/dist/testing/data-explorer.js +5 -3
  57. package/dist/types/types.d.ts +14 -14
  58. package/dist/ui/api.d.ts.map +1 -1
  59. package/dist/ui/api.js +3 -2
  60. package/dist/ui-web/assets/index-D4rYm-Xz.css +1 -0
  61. package/dist/ui-web/assets/{index-DrTfl0Ts.js → index-DzZ7vBk4.js} +47 -47
  62. package/dist/ui-web/index.html +2 -2
  63. package/dist/utils/fs-utils.d.ts.map +1 -1
  64. package/dist/utils/fs-utils.js +4 -4
  65. package/package.json +4 -5
  66. package/src/ai/providers/rtzr/utils.ts +1 -1
  67. package/src/api/config.ts +0 -8
  68. package/src/api/sonamu.ts +1 -51
  69. package/src/auth/audit-log/builders.ts +791 -0
  70. package/src/auth/audit-log/events.ts +149 -0
  71. package/src/auth/audit-log/plugin.ts +913 -0
  72. package/src/auth/audit-log-ingestor.ts +3 -4
  73. package/src/auth/index.ts +2 -0
  74. package/src/auth/plugins/entity-definitions/admin.ts +3 -3
  75. package/src/auth/plugins/entity-definitions/audit-log.ts +2 -2
  76. package/src/bin/fixture.ts +143 -0
  77. package/src/database/_batch_update.ts +1 -1
  78. package/src/database/upsert-builder.ts +3 -3
  79. package/src/dict/sonamu-dictionary.ts +1 -1
  80. package/src/entity/entity-manager.ts +10 -3
  81. package/src/migration/code-generation.ts +1 -6
  82. package/src/shared/app.shared.ts.txt +60 -6
  83. package/src/shared/web.shared.ts.txt +60 -5
  84. package/src/syncer/syncer.ts +1 -11
  85. package/src/template/implementations/entry-server.template.ts +1 -1
  86. package/src/template/implementations/generated.template.ts +1 -0
  87. package/src/template/implementations/generated_sso.template.ts +1 -0
  88. package/src/template/implementations/queries.template.ts +10 -1
  89. package/src/template/implementations/sd.template.ts +1 -1
  90. package/src/template/implementations/services.template.ts +62 -6
  91. package/src/template/zod-converter.ts +2 -1
  92. package/src/testing/data-explorer.ts +3 -2
  93. package/src/ui/api.ts +10 -1
  94. package/src/utils/fs-utils.ts +6 -4
  95. package/dist/auth/audit-log-proxy-types.d.ts +0 -23
  96. package/dist/auth/audit-log-proxy-types.d.ts.map +0 -1
  97. package/dist/auth/audit-log-proxy-types.js +0 -1
  98. package/dist/ui-web/assets/index-Dr8pRJC_.css +0 -1
  99. package/src/auth/audit-log-proxy-types.ts +0 -23
@@ -0,0 +1,427 @@
1
+ import { DB, init_db } from "../../database/db.js";
2
+ import { ROUTES } from "./events.js";
3
+ import { buildAuditEventCatalog } from "./builders.js";
4
+ import { ingestAuditEvent } from "../audit-log-ingestor.js";
5
+ import { getLogger } from "@logtape/logtape";
6
+ import { createAuthMiddleware } from "better-auth/api";
7
+
8
+ //#region src/auth/audit-log/plugin.ts
9
+ init_db();
10
+ const stripQuery = (value) => value.split("?")[0] || value;
11
+ const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12
+ const routeToRegex = (route) => {
13
+ const pattern = escapeRegex(stripQuery(route)).replace(/\/:([^/]+)/g, "/[^/]+");
14
+ return new RegExp(`${pattern}(?:$|[/?])`);
15
+ };
16
+ const matchesAnyRoute = (routePath, routes) => {
17
+ if (!routePath) return false;
18
+ const cleanPath = stripQuery(routePath);
19
+ return routes.some((route) => routeToRegex(route).test(cleanPath));
20
+ };
21
+ const LOGIN_PATHS = [
22
+ ROUTES.SIGN_IN_SOCIAL_CALLBACK,
23
+ ROUTES.SIGN_IN_OAUTH_CALLBACK,
24
+ ROUTES.SIGN_IN_EMAIL,
25
+ ROUTES.SIGN_IN_SOCIAL,
26
+ ROUTES.SIGN_IN_EMAIL_OTP,
27
+ ROUTES.SIGN_UP_EMAIL
28
+ ];
29
+ const getLoginMethod = (ctxPath, paramsId) => {
30
+ if (!ctxPath) return null;
31
+ if (matchesAnyRoute(ctxPath, LOGIN_PATHS)) {
32
+ if (paramsId) return paramsId;
33
+ return ctxPath.split("/").pop() ?? null;
34
+ }
35
+ return null;
36
+ };
37
+ const getTriggerInfo = (ctxPath, sessionUserId, userId) => {
38
+ const resolved = sessionUserId ?? userId;
39
+ const triggerContext = resolved === userId ? "user" : matchesAnyRoute(ctxPath, [ROUTES.ADMIN_ROUTE]) ? "admin" : matchesAnyRoute(ctxPath, [ROUTES.DASH_ROUTE]) ? "dashboard" : resolved === "unknown" ? "user" : "unknown";
40
+ return {
41
+ triggeredBy: resolved,
42
+ triggerContext
43
+ };
44
+ };
45
+ const getOrganizationTriggerInfo = (user) => ({
46
+ triggeredBy: user?.id ?? "unknown",
47
+ triggerContext: "organization"
48
+ });
49
+ const narrowRequestCtx = (raw) => {
50
+ if (!raw || typeof raw !== "object") return null;
51
+ const candidate = raw;
52
+ if (!candidate.context || typeof candidate.context !== "object") return null;
53
+ return raw;
54
+ };
55
+ const fetchUserBy = async (ctx, field, value) => {
56
+ if (!value) return null;
57
+ const adapter = ctx.context.adapter;
58
+ if (!adapter) return null;
59
+ try {
60
+ const row = await adapter.findOne({
61
+ model: "user",
62
+ select: [
63
+ "id",
64
+ "name",
65
+ "email"
66
+ ],
67
+ where: [{
68
+ field,
69
+ value
70
+ }]
71
+ });
72
+ if (!row) return null;
73
+ return {
74
+ id: String(row.id),
75
+ name: typeof row.name === "string" ? row.name : undefined,
76
+ email: typeof row.email === "string" ? row.email : undefined
77
+ };
78
+ } catch {
79
+ return null;
80
+ }
81
+ };
82
+ const isNonEmptyString = (v) => typeof v === "string" && v.length > 0;
83
+ const IP_HEADER_ORDER = [
84
+ "cf-connecting-ip",
85
+ "x-forwarded-for",
86
+ "x-real-ip",
87
+ "x-vercel-forwarded-for"
88
+ ];
89
+ const readHeader = (headers, key) => {
90
+ if (!headers) return null;
91
+ if (headers instanceof Headers) {
92
+ return headers.get(key);
93
+ }
94
+ if (typeof headers === "object") {
95
+ const map = headers;
96
+ const v = map[key] ?? map[key.toLowerCase()];
97
+ if (typeof v === "string") return v;
98
+ if (Array.isArray(v) && typeof v[0] === "string") return v[0];
99
+ }
100
+ return null;
101
+ };
102
+ const extractLocationFromHeaders = (headers) => {
103
+ let ipAddress = null;
104
+ for (const key of IP_HEADER_ORDER) {
105
+ const raw = readHeader(headers, key);
106
+ if (typeof raw === "string" && raw.length > 0) {
107
+ const first = raw.split(",")[0]?.trim();
108
+ if (first) {
109
+ ipAddress = first;
110
+ break;
111
+ }
112
+ }
113
+ }
114
+ const countryCode = readHeader(headers, "cf-ipcountry");
115
+ const city = readHeader(headers, "cf-ipcity");
116
+ return {
117
+ ipAddress: ipAddress ?? undefined,
118
+ city: city ?? undefined,
119
+ country: undefined,
120
+ countryCode: countryCode ?? undefined
121
+ };
122
+ };
123
+ const wrapOrgHook = (hooks, name, handler) => {
124
+ const prev = hooks[name];
125
+ hooks[name] = async (...args) => {
126
+ await handler(args[0]);
127
+ if (prev) return prev(...args);
128
+ return undefined;
129
+ };
130
+ };
131
+ /**
132
+ * Better Auth databaseHooks/organizationHooks/middleware에서 수집한
133
+ * 이벤트를 `DB.getDB("w")`로 얻은 knex에 `ingestAuditEvent`로 적재한다.
134
+ *
135
+ * - dash(@better-auth/infra)의 audit-event 수집 훅 구조를 참고해 Sonamu 내부 적재 경로로 포팅한다.
136
+ * - dash의 infra 연결/API endpoint 제공 범위는 포함하지 않고, audit-event emit/ingest 경로만 유지한다.
137
+ * - security 4종은 R1 결정에 따라 scope out (builders.ts의 TODO 주석 참조).
138
+ */
139
+ function sonamuAuditLog() {
140
+ const logger = getLogger(["sonamu", "audit-log"]);
141
+ const catalog = buildAuditEventCatalog();
142
+ const processedBulkOperationContexts = new WeakSet();
143
+ const emit = async (event) => {
144
+ try {
145
+ await ingestAuditEvent(DB.getDB("w"), event);
146
+ } catch (err) {
147
+ logger.error("audit event ingest failed: {error}", { error: err });
148
+ }
149
+ };
150
+ const triggerFor = (ctx, subjectUserId) => getTriggerInfo(ctx.path, ctx.context.session?.session?.userId ?? null, subjectUserId);
151
+ const locationFor = (ctx) => ctx.context.location ?? undefined;
152
+ return {
153
+ id: "sonamu-audit-log",
154
+ init(pluginCtx) {
155
+ installOrganizationHooks(pluginCtx, catalog, emit, logger);
156
+ return { options: { databaseHooks: {
157
+ user: {
158
+ create: { after: async (rawUser, rawCtx) => {
159
+ const ctx = narrowRequestCtx(rawCtx);
160
+ if (!ctx) return;
161
+ const user = rawUser;
162
+ await emit(catalog.user.trackUserSignedUp(user, triggerFor(ctx, user.id), locationFor(ctx)));
163
+ } },
164
+ update: { after: async (rawUser, rawCtx) => {
165
+ const ctx = narrowRequestCtx(rawCtx);
166
+ if (!ctx) return;
167
+ const user = rawUser;
168
+ const path = ctx.path;
169
+ const trigger = triggerFor(ctx, user.id);
170
+ const location = locationFor(ctx);
171
+ if (matchesAnyRoute(path, [ROUTES.UPDATE_USER, ROUTES.DASH_UPDATE_USER])) {
172
+ const updatedFields = Object.keys(ctx.body ?? {});
173
+ const isOnlyImageUpdate = updatedFields.length === 1 && updatedFields[0] === "image";
174
+ const isOnlyEmailVerifiedUpdate = updatedFields.length === 1 && updatedFields[0] === "emailVerified";
175
+ const hasEmailVerifiedUpdate = updatedFields.includes("emailVerified");
176
+ if (isOnlyEmailVerifiedUpdate && user.emailVerified) {
177
+ await emit(catalog.user.trackUserEmailVerified(user, trigger, location));
178
+ } else if (isOnlyImageUpdate && user.image) {
179
+ await emit(catalog.user.trackUserProfileImageUpdated(user, trigger, location));
180
+ } else if (!isOnlyImageUpdate && !isOnlyEmailVerifiedUpdate) {
181
+ await emit(catalog.user.trackUserProfileUpdated(user, updatedFields, trigger, location));
182
+ if (hasEmailVerifiedUpdate && user.emailVerified) {
183
+ await emit(catalog.user.trackUserEmailVerified(user, trigger, location));
184
+ }
185
+ }
186
+ } else if (matchesAnyRoute(path, [ROUTES.CHANGE_EMAIL])) {
187
+ const updatedFields = Object.keys(ctx.body ?? {});
188
+ await emit(catalog.user.trackUserProfileUpdated(user, updatedFields, trigger, location));
189
+ }
190
+ if (matchesAnyRoute(path, [ROUTES.VERIFY_EMAIL]) && user.emailVerified) {
191
+ await emit(catalog.user.trackUserEmailVerified(user, trigger, location));
192
+ }
193
+ if (matchesAnyRoute(path, [ROUTES.ADMIN_BAN_USER]) && "banned" in user && user.banned) {
194
+ await emit(catalog.user.trackUserBanned(user, trigger, location));
195
+ }
196
+ if (matchesAnyRoute(path, [ROUTES.ADMIN_UNBAN_USER]) && "banned" in user && !user.banned) {
197
+ await emit(catalog.user.trackUserUnBanned(user, trigger, location));
198
+ }
199
+ } },
200
+ delete: { after: async (rawUser, rawCtx) => {
201
+ const ctx = narrowRequestCtx(rawCtx);
202
+ if (!ctx) return;
203
+ const user = rawUser;
204
+ await emit(catalog.user.trackUserDeleted(user, triggerFor(ctx, user.id), locationFor(ctx)));
205
+ } }
206
+ },
207
+ session: {
208
+ create: {
209
+ before: async (rawSession, rawCtx) => {
210
+ void rawSession;
211
+ const ctx = narrowRequestCtx(rawCtx);
212
+ if (!ctx) return undefined;
213
+ return { data: { loginMethod: getLoginMethod(ctx.path, ctx.params?.id) } };
214
+ },
215
+ after: async (rawSession, rawCtx) => {
216
+ const ctx = narrowRequestCtx(rawCtx);
217
+ if (!ctx) return;
218
+ const session = rawSession;
219
+ if (!session.userId) return;
220
+ const location = locationFor(ctx);
221
+ const loginMethod = getLoginMethod(ctx.path, ctx.params?.id) ?? undefined;
222
+ const enrichedSession = {
223
+ ...session,
224
+ loginMethod: loginMethod ?? session.loginMethod ?? null
225
+ };
226
+ const user = await fetchUserBy(ctx, "id", session.userId);
227
+ let trigger;
228
+ if (matchesAnyRoute(ctx.path, [
229
+ ROUTES.SIGN_IN,
230
+ ROUTES.SIGN_UP,
231
+ ROUTES.SIGN_IN_SOCIAL_CALLBACK,
232
+ ROUTES.SIGN_IN_OAUTH_CALLBACK
233
+ ])) {
234
+ trigger = getTriggerInfo(ctx.path, session.userId, session.userId);
235
+ await emit(catalog.session.trackUserSignedIn(enrichedSession, user, trigger, location));
236
+ } else {
237
+ trigger = triggerFor(ctx, session.userId);
238
+ }
239
+ await emit(catalog.session.trackSessionCreated(enrichedSession, user, trigger, location));
240
+ if (isNonEmptyString(session.impersonatedBy)) {
241
+ const impersonator = await fetchUserBy(ctx, "id", session.impersonatedBy);
242
+ await emit(catalog.session.trackUserImpersonated(enrichedSession, user, impersonator, {
243
+ triggeredBy: session.impersonatedBy,
244
+ triggerContext: trigger.triggerContext
245
+ }, location));
246
+ }
247
+ }
248
+ },
249
+ delete: { after: async (rawSession, rawCtx) => {
250
+ const ctx = narrowRequestCtx(rawCtx);
251
+ if (!ctx) return;
252
+ const session = rawSession;
253
+ const location = locationFor(ctx);
254
+ const enrichedSession = { ...session };
255
+ const user = await fetchUserBy(ctx, "id", session.userId);
256
+ const trigger = triggerFor(ctx, session.userId);
257
+ if (matchesAnyRoute(ctx.path, [
258
+ ROUTES.REVOKE_ALL_SESSIONS,
259
+ ROUTES.ADMIN_REVOKE_USER_SESSIONS,
260
+ ROUTES.DASH_REVOKE_SESSIONS_ALL,
261
+ ROUTES.DASH_BAN_USER
262
+ ])) {
263
+ if (!processedBulkOperationContexts.has(ctx)) {
264
+ await emit(catalog.session.trackSessionRevokedAll(enrichedSession, user, trigger));
265
+ processedBulkOperationContexts.add(ctx);
266
+ }
267
+ } else if (matchesAnyRoute(ctx.path, [ROUTES.SIGN_OUT])) {
268
+ await emit(catalog.session.trackUserSignedOut(enrichedSession, user, trigger, location));
269
+ } else {
270
+ await emit(catalog.session.trackSessionRevoked(enrichedSession, user, trigger, location));
271
+ }
272
+ if (isNonEmptyString(session.impersonatedBy)) {
273
+ const impersonator = await fetchUserBy(ctx, "id", session.impersonatedBy);
274
+ await emit(catalog.session.trackUserImpersonationStop(enrichedSession, user, impersonator, trigger, location));
275
+ }
276
+ } }
277
+ },
278
+ account: {
279
+ create: { after: async (rawAccount, rawCtx) => {
280
+ const ctx = narrowRequestCtx(rawCtx);
281
+ if (!ctx) return;
282
+ const account = rawAccount;
283
+ if (!account.userId) return;
284
+ const user = await fetchUserBy(ctx, "id", account.userId);
285
+ await emit(catalog.account.trackAccountLinking(account, user, triggerFor(ctx, account.userId), locationFor(ctx)));
286
+ } },
287
+ update: { after: async (rawAccount, rawCtx) => {
288
+ const ctx = narrowRequestCtx(rawCtx);
289
+ if (!ctx) return;
290
+ const account = rawAccount;
291
+ if (!account.userId) return;
292
+ if (!matchesAnyRoute(ctx.path, [
293
+ ROUTES.CHANGE_PASSWORD,
294
+ ROUTES.SET_PASSWORD,
295
+ ROUTES.RESET_PASSWORD,
296
+ ROUTES.ADMIN_SET_PASSWORD
297
+ ])) {
298
+ return;
299
+ }
300
+ const user = await fetchUserBy(ctx, "id", account.userId);
301
+ await emit(catalog.account.trackAccountPasswordChange(account, user, triggerFor(ctx, account.userId), locationFor(ctx)));
302
+ } },
303
+ delete: { after: async (rawAccount, rawCtx) => {
304
+ const ctx = narrowRequestCtx(rawCtx);
305
+ if (!ctx) return;
306
+ const account = rawAccount;
307
+ if (!account.userId) return;
308
+ const user = await fetchUserBy(ctx, "id", account.userId);
309
+ await emit(catalog.account.trackAccountUnlink(account, user, triggerFor(ctx, account.userId), locationFor(ctx)));
310
+ } }
311
+ },
312
+ verification: {
313
+ create: { after: async (rawVerification, rawCtx) => {
314
+ const ctx = narrowRequestCtx(rawCtx);
315
+ if (!ctx) return;
316
+ if (!matchesAnyRoute(ctx.path, [ROUTES.REQUEST_PASSWORD_RESET])) return;
317
+ const verification = rawVerification;
318
+ const sessionUserId = ctx.context.session?.user?.id ?? "unknown";
319
+ const trigger = getTriggerInfo(ctx.path, sessionUserId, sessionUserId);
320
+ const user = await fetchUserBy(ctx, "id", verification.value);
321
+ await emit(catalog.verification.trackPasswordResetRequest(verification, user, trigger, locationFor(ctx)));
322
+ } },
323
+ delete: { after: async (rawVerification, rawCtx) => {
324
+ const ctx = narrowRequestCtx(rawCtx);
325
+ if (!ctx) return;
326
+ if (!matchesAnyRoute(ctx.path, [ROUTES.RESET_PASSWORD])) return;
327
+ const verification = rawVerification;
328
+ const sessionUserId = ctx.context.session?.user?.id ?? "unknown";
329
+ const trigger = getTriggerInfo(ctx.path, sessionUserId, sessionUserId);
330
+ const user = await fetchUserBy(ctx, "id", verification.value);
331
+ await emit(catalog.verification.trackPasswordResetRequestCompletion(verification, user, trigger, locationFor(ctx)));
332
+ } }
333
+ }
334
+ } } };
335
+ },
336
+ hooks: {
337
+ before: [{
338
+ matcher: () => true,
339
+ handler: createAuthMiddleware(async (rawCtx) => {
340
+ const ctx = rawCtx;
341
+ if (!ctx.context) return;
342
+ const headers = ctx.headers ?? ctx.request?.headers;
343
+ ctx.context.location = extractLocationFromHeaders(headers);
344
+ })
345
+ }],
346
+ after: [{
347
+ matcher: (ctx) => {
348
+ const c = ctx;
349
+ if (c.request?.method !== "GET") return true;
350
+ if (!c.request.url) return false;
351
+ try {
352
+ const p = new URL(c.request.url).pathname;
353
+ return matchesAnyRoute(p, [ROUTES.SIGN_IN_SOCIAL_CALLBACK, ROUTES.SIGN_IN_OAUTH_CALLBACK]);
354
+ } catch {
355
+ return false;
356
+ }
357
+ },
358
+ handler: createAuthMiddleware(async (rawCtx) => {
359
+ const ctx = narrowRequestCtx(rawCtx);
360
+ if (!ctx) return;
361
+ const sessionUser = ctx.context.session?.user;
362
+ const sessionUserId = sessionUser?.id ?? "unknown";
363
+ const trigger = getTriggerInfo(ctx.path, sessionUserId, sessionUserId);
364
+ const location = locationFor(ctx);
365
+ const returned = ctx.context.returned;
366
+ const isErrored = returned instanceof Error;
367
+ if (matchesAnyRoute(ctx.path, [ROUTES.SEND_VERIFICATION_EMAIL]) && ctx.context.session && !isErrored) {
368
+ const sessionEntity = ctx.context.session.session;
369
+ const user = ctx.context.session.user;
370
+ if (sessionEntity && user) {
371
+ await emit(catalog.session.trackEmailVerificationSent(sessionEntity, user, trigger));
372
+ }
373
+ }
374
+ const body = ctx.body ?? null;
375
+ if (matchesAnyRoute(ctx.path, [ROUTES.SIGN_IN_EMAIL, ROUTES.SIGN_IN_EMAIL_OTP]) && isErrored && body?.email) {
376
+ const user = await fetchUserBy(ctx, "email", body.email);
377
+ await emit(catalog.session.trackEmailSignInAttempt({
378
+ email: body.email,
379
+ loginMethod: getLoginMethod(ctx.path, ctx.params?.id)
380
+ }, user, trigger, location));
381
+ }
382
+ if (matchesAnyRoute(ctx.path, [ROUTES.SIGN_IN_SOCIAL]) && isErrored && body?.provider && body?.idToken) {
383
+ await emit(catalog.session.trackSocialSignInAttempt({ loginMethod: getLoginMethod(ctx.path, ctx.params?.id) }, null, trigger, location));
384
+ }
385
+ if (matchesAnyRoute(ctx.path, [ROUTES.SIGN_IN_SOCIAL_CALLBACK]) && isErrored) {
386
+ await emit(catalog.session.trackSocialSignInRedirectionAttempt({ loginMethod: getLoginMethod(ctx.path, ctx.params?.id) }, null, trigger, location));
387
+ }
388
+ })
389
+ }]
390
+ }
391
+ };
392
+ }
393
+ function installOrganizationHooks(pluginCtx, catalog, emit, logger) {
394
+ const getPlugin = pluginCtx?.getPlugin;
395
+ const organizationPlugin = typeof getPlugin === "function" ? getPlugin.call(pluginCtx, "organization") : null;
396
+ if (!organizationPlugin || typeof organizationPlugin !== "object") {
397
+ logger.debug("organization plugin not active; skipping instrumentation");
398
+ return;
399
+ }
400
+ const orgPlugin = organizationPlugin;
401
+ orgPlugin.options = orgPlugin.options ?? {};
402
+ const hooks = orgPlugin.options.organizationHooks = orgPlugin.options.organizationHooks ?? {};
403
+ wrapOrgHook(hooks, "afterCreateOrganization", async (p) => emit(catalog.organization.trackOrganizationCreated(p.organization, getOrganizationTriggerInfo(p.user))));
404
+ wrapOrgHook(hooks, "afterUpdateOrganization", async (p) => {
405
+ if (!p.organization) return;
406
+ await emit(catalog.organization.trackOrganizationUpdated(p.organization, getOrganizationTriggerInfo(p.user)));
407
+ });
408
+ wrapOrgHook(hooks, "afterAddMember", async (p) => emit(catalog.member.trackOrganizationMemberAdded(p.organization, p.member, p.user, getOrganizationTriggerInfo(p.user))));
409
+ wrapOrgHook(hooks, "afterRemoveMember", async (p) => emit(catalog.member.trackOrganizationMemberRemoved(p.organization, p.member, p.user, getOrganizationTriggerInfo(p.user))));
410
+ wrapOrgHook(hooks, "afterUpdateMemberRole", async (p) => emit(catalog.member.trackOrganizationMemberRoleUpdated(p.organization, p.member, p.user, p.previousRole, getOrganizationTriggerInfo(p.user))));
411
+ wrapOrgHook(hooks, "afterCreateInvitation", async (p) => emit(catalog.invitation.trackOrganizationMemberInvited(p.organization, p.invitation, p.inviter, getOrganizationTriggerInfo(p.inviter))));
412
+ wrapOrgHook(hooks, "afterAcceptInvitation", async (p) => emit(catalog.invitation.trackOrganizationMemberInviteAccepted(p.organization, p.invitation, p.member, p.user, getOrganizationTriggerInfo(p.user))));
413
+ wrapOrgHook(hooks, "afterRejectInvitation", async (p) => emit(catalog.invitation.trackOrganizationMemberInviteRejected(p.organization, p.invitation, p.user, getOrganizationTriggerInfo(p.user))));
414
+ wrapOrgHook(hooks, "afterCancelInvitation", async (p) => emit(catalog.invitation.trackOrganizationMemberInviteCanceled(p.organization, p.invitation, p.cancelledBy, getOrganizationTriggerInfo(p.cancelledBy))));
415
+ wrapOrgHook(hooks, "afterCreateTeam", async (p) => emit(catalog.team.trackOrganizationTeamCreated(p.organization, p.team, getOrganizationTriggerInfo(p.user))));
416
+ wrapOrgHook(hooks, "afterUpdateTeam", async (p) => {
417
+ if (!p.team) return;
418
+ await emit(catalog.team.trackOrganizationTeamUpdated(p.organization, p.team, getOrganizationTriggerInfo(p.user)));
419
+ });
420
+ wrapOrgHook(hooks, "afterDeleteTeam", async (p) => emit(catalog.team.trackOrganizationTeamDeleted(p.organization, p.team, getOrganizationTriggerInfo(p.user))));
421
+ wrapOrgHook(hooks, "afterAddTeamMember", async (p) => emit(catalog.team.trackOrganizationTeamMemberAdded(p.organization, p.team, p.user, p.teamMember, getOrganizationTriggerInfo(p.user))));
422
+ wrapOrgHook(hooks, "afterRemoveTeamMember", async (p) => emit(catalog.team.trackOrganizationTeamMemberRemoved(p.organization, p.team, p.user, p.teamMember, getOrganizationTriggerInfo(p.user))));
423
+ }
424
+
425
+ //#endregion
426
+ export { sonamuAuditLog };
427
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwibmFtZXMiOlsiaXBBZGRyZXNzOiBzdHJpbmcgfCBudWxsIiwiZW5yaWNoZWRTZXNzaW9uOiBTZXNzaW9uU25hcHNob3QiLCJ0cmlnZ2VyOiBCdWlsZGVyVHJpZ2dlciJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hdXRoL2F1ZGl0LWxvZy9wbHVnaW4udHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZ2V0TG9nZ2VyIH0gZnJvbSBcIkBsb2d0YXBlL2xvZ3RhcGVcIjtcbmltcG9ydCB7IHR5cGUgQmV0dGVyQXV0aFBsdWdpbiB9IGZyb20gXCJiZXR0ZXItYXV0aFwiO1xuaW1wb3J0IHsgY3JlYXRlQXV0aE1pZGRsZXdhcmUgfSBmcm9tIFwiYmV0dGVyLWF1dGgvYXBpXCI7XG5cbmltcG9ydCB7IERCIH0gZnJvbSBcIi4uLy4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyBpbmdlc3RBdWRpdEV2ZW50IH0gZnJvbSBcIi4uL2F1ZGl0LWxvZy1pbmdlc3RvclwiO1xuaW1wb3J0IHsgYnVpbGRBdWRpdEV2ZW50Q2F0YWxvZyB9IGZyb20gXCIuL2J1aWxkZXJzXCI7XG5pbXBvcnQge1xuICB0eXBlIEFjY291bnRTbmFwc2hvdCxcbiAgdHlwZSBBdWRpdExvZ0V2ZW50LFxuICB0eXBlIEJ1aWxkZXJMb2NhdGlvbixcbiAgdHlwZSBCdWlsZGVyVHJpZ2dlcixcbiAgdHlwZSBJbnZpdGF0aW9uU25hcHNob3QsXG4gIHR5cGUgTWVtYmVyU25hcHNob3QsXG4gIHR5cGUgT3JnYW5pemF0aW9uU25hcHNob3QsXG4gIFJPVVRFUyxcbiAgdHlwZSBTZXNzaW9uU25hcHNob3QsXG4gIHR5cGUgVGVhbVNuYXBzaG90LFxuICB0eXBlIFVzZXJQcm9maWxlTGl0ZSxcbiAgdHlwZSBVc2VyU25hcHNob3QsXG4gIHR5cGUgVmVyaWZpY2F0aW9uU25hcHNob3QsXG59IGZyb20gXCIuL2V2ZW50c1wiO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyDrnbzsmrDtjIUv7Yq466as6rGwIOycoO2LuFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuY29uc3Qgc3RyaXBRdWVyeSA9ICh2YWx1ZTogc3RyaW5nKTogc3RyaW5nID0+IHZhbHVlLnNwbGl0KFwiP1wiKVswXSB8fCB2YWx1ZTtcbmNvbnN0IGVzY2FwZVJlZ2V4ID0gKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcgPT4gdmFsdWUucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csIFwiXFxcXCQmXCIpO1xuY29uc3Qgcm91dGVUb1JlZ2V4ID0gKHJvdXRlOiBzdHJpbmcpOiBSZWdFeHAgPT4ge1xuICBjb25zdCBwYXR0ZXJuID0gZXNjYXBlUmVnZXgoc3RyaXBRdWVyeShyb3V0ZSkpLnJlcGxhY2UoL1xcLzooW14vXSspL2csIFwiL1teL10rXCIpO1xuICByZXR1cm4gbmV3IFJlZ0V4cChgJHtwYXR0ZXJufSg/OiR8Wy8/XSlgKTtcbn07XG5jb25zdCBtYXRjaGVzQW55Um91dGUgPSAocm91dGVQYXRoOiBzdHJpbmcgfCB1bmRlZmluZWQsIHJvdXRlczogcmVhZG9ubHkgc3RyaW5nW10pOiBib29sZWFuID0+IHtcbiAgaWYgKCFyb3V0ZVBhdGgpIHJldHVybiBmYWxzZTtcbiAgY29uc3QgY2xlYW5QYXRoID0gc3RyaXBRdWVyeShyb3V0ZVBhdGgpO1xuICByZXR1cm4gcm91dGVzLnNvbWUoKHJvdXRlKSA9PiByb3V0ZVRvUmVnZXgocm91dGUpLnRlc3QoY2xlYW5QYXRoKSk7XG59O1xuXG5jb25zdCBMT0dJTl9QQVRIUyA9IFtcbiAgUk9VVEVTLlNJR05fSU5fU09DSUFMX0NBTExCQUNLLFxuICBST1VURVMuU0lHTl9JTl9PQVVUSF9DQUxMQkFDSyxcbiAgUk9VVEVTLlNJR05fSU5fRU1BSUwsXG4gIFJPVVRFUy5TSUdOX0lOX1NPQ0lBTCxcbiAgUk9VVEVTLlNJR05fSU5fRU1BSUxfT1RQLFxuICBST1VURVMuU0lHTl9VUF9FTUFJTCxcbl0gYXMgY29uc3Q7XG5cbi8vIGRhc2ggMzE5LTMyMyDrr7jrn6w6IO2YhOyerCDsmpTssq0gcGF0aOyXkOyEnCDroZzqt7jsnbgg67Cp7Iud7J2EIOy2lOy2nO2VnOuLpC5cbmNvbnN0IGdldExvZ2luTWV0aG9kID0gKGN0eFBhdGg6IHN0cmluZyB8IHVuZGVmaW5lZCwgcGFyYW1zSWQ/OiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsID0+IHtcbiAgaWYgKCFjdHhQYXRoKSByZXR1cm4gbnVsbDtcbiAgaWYgKG1hdGNoZXNBbnlSb3V0ZShjdHhQYXRoLCBMT0dJTl9QQVRIUykpIHtcbiAgICBpZiAocGFyYW1zSWQpIHJldHVybiBwYXJhbXNJZDtcbiAgICByZXR1cm4gY3R4UGF0aC5zcGxpdChcIi9cIikucG9wKCkgPz8gbnVsbDtcbiAgfVxuICByZXR1cm4gbnVsbDtcbn07XG5cbi8vIGRhc2ggNzk3LTgwMyDrr7jrn6w6IOyEuOyFmC/smpTssq3sl5DshJwg7Yq466as6rGwIOyjvOyytOyZgCDsu6jthY3siqTtirjrpbwg64+E7Lac7ZWc64ukLlxuY29uc3QgZ2V0VHJpZ2dlckluZm8gPSAoXG4gIGN0eFBhdGg6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgc2Vzc2lvblVzZXJJZDogc3RyaW5nIHwgbnVsbCxcbiAgdXNlcklkOiBzdHJpbmcsXG4pOiBCdWlsZGVyVHJpZ2dlciA9PiB7XG4gIGNvbnN0IHJlc29sdmVkID0gc2Vzc2lvblVzZXJJZCA/PyB1c2VySWQ7XG4gIGNvbnN0IHRyaWdnZXJDb250ZXh0ID1cbiAgICByZXNvbHZlZCA9PT0gdXNlcklkXG4gICAgICA/IFwidXNlclwiXG4gICAgICA6IG1hdGNoZXNBbnlSb3V0ZShjdHhQYXRoLCBbUk9VVEVTLkFETUlOX1JPVVRFXSlcbiAgICAgICAgPyBcImFkbWluXCJcbiAgICAgICAgOiBtYXRjaGVzQW55Um91dGUoY3R4UGF0aCwgW1JPVVRFUy5EQVNIX1JPVVRFXSlcbiAgICAgICAgICA/IFwiZGFzaGJvYXJkXCJcbiAgICAgICAgICA6IHJlc29sdmVkID09PSBcInVua25vd25cIlxuICAgICAgICAgICAgPyBcInVzZXJcIlxuICAgICAgICAgICAgOiBcInVua25vd25cIjtcbiAgcmV0dXJuIHsgdHJpZ2dlcmVkQnk6IHJlc29sdmVkLCB0cmlnZ2VyQ29udGV4dCB9O1xufTtcblxuLy8gZGFzaCA4MDktODE0IOuvuOufrDogb3JnYW5pemF0aW9uIGhvb2vsnYAg7J247KadIOy7qO2FjeyKpO2KuCDsl4bsnbTrj4Qg7Zi47Lac65CY66+A66GcXG4vLyDso7zslrTsp4QgdXNlciDqsJ3ssrTroZzrtoDthLAg7Yq466as6rGwIOygleuztOulvCDtlanshLHtlZzri6QuXG5jb25zdCBnZXRPcmdhbml6YXRpb25UcmlnZ2VySW5mbyA9ICh1c2VyOiB7IGlkPzogc3RyaW5nIH0gfCBudWxsIHwgdW5kZWZpbmVkKTogQnVpbGRlclRyaWdnZXIgPT4gKHtcbiAgdHJpZ2dlcmVkQnk6IHVzZXI/LmlkID8/IFwidW5rbm93blwiLFxuICB0cmlnZ2VyQ29udGV4dDogXCJvcmdhbml6YXRpb25cIixcbn0pO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBiZXR0ZXItYXV0aCBjdHgg7YOA7J6FIGhlbHBlcnMgKOuCtOu2gCBzaGFwZeydgCDrn7Dtg4DsnoQg6rWs7KGw66W8IOq4sOykgOycvOuhnCDsooHtmIAg7IKs7Jqp7ZWc64ukKVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxudHlwZSBCZXR0ZXJBdXRoUmVxdWVzdEN0eCA9IHtcbiAgcGF0aD86IHN0cmluZztcbiAgYm9keT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbCB8IHVuZGVmaW5lZDtcbiAgcGFyYW1zPzogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPiB8IG51bGwgfCB1bmRlZmluZWQ7XG4gIGNvbnRleHQ6IHtcbiAgICBzZXNzaW9uPzoge1xuICAgICAgc2Vzc2lvbj86IHsgdXNlcklkPzogc3RyaW5nIH07XG4gICAgICB1c2VyPzogeyBpZD86IHN0cmluZyB9O1xuICAgIH0gfCBudWxsO1xuICAgIGxvY2F0aW9uPzogQnVpbGRlckxvY2F0aW9uIHwgbnVsbDtcbiAgICBhZGFwdGVyPzoge1xuICAgICAgZmluZE9uZTogKGFyZ3M6IHtcbiAgICAgICAgbW9kZWw6IHN0cmluZztcbiAgICAgICAgc2VsZWN0Pzogc3RyaW5nW107XG4gICAgICAgIHdoZXJlOiB7IGZpZWxkOiBzdHJpbmc7IHZhbHVlOiB1bmtub3duIH1bXTtcbiAgICAgIH0pID0+IFByb21pc2U8UmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCBudWxsPjtcbiAgICB9O1xuICAgIHJldHVybmVkPzogdW5rbm93bjtcbiAgfTtcbn07XG5cbi8vIGRhdGFiYXNlSG9va3MgYWZ0ZXIg7L2c67Cx7J2YIGN0eOuKlCDshKDtg53soIHsnbTrqbAgc2hhcGXsnYQg65+w7YOA7J6E7JeQ7IScIOyige2ejOuLpC5cbmNvbnN0IG5hcnJvd1JlcXVlc3RDdHggPSAocmF3OiB1bmtub3duKTogQmV0dGVyQXV0aFJlcXVlc3RDdHggfCBudWxsID0+IHtcbiAgaWYgKCFyYXcgfHwgdHlwZW9mIHJhdyAhPT0gXCJvYmplY3RcIikgcmV0dXJuIG51bGw7XG4gIGNvbnN0IGNhbmRpZGF0ZSA9IHJhdyBhcyB7IGNvbnRleHQ/OiB1bmtub3duIH07XG4gIGlmICghY2FuZGlkYXRlLmNvbnRleHQgfHwgdHlwZW9mIGNhbmRpZGF0ZS5jb250ZXh0ICE9PSBcIm9iamVjdFwiKSByZXR1cm4gbnVsbDtcbiAgcmV0dXJuIHJhdyBhcyBCZXR0ZXJBdXRoUmVxdWVzdEN0eDtcbn07XG5cbi8vIGFkYXB0ZXIuZmluZE9uZSDtmLjstpwg7Iuk7YyoIOyLnCBudWxs7J2EIOuwmO2ZmO2VnOuLpC4gZGFzaCDtl6ztjbzsmYAg64+Z7J28IOygleyxhS5cbmNvbnN0IGZldGNoVXNlckJ5ID0gYXN5bmMgKFxuICBjdHg6IEJldHRlckF1dGhSZXF1ZXN0Q3R4LFxuICBmaWVsZDogXCJpZFwiIHwgXCJlbWFpbFwiLFxuICB2YWx1ZTogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCxcbik6IFByb21pc2U8VXNlclByb2ZpbGVMaXRlPiA9PiB7XG4gIGlmICghdmFsdWUpIHJldHVybiBudWxsO1xuICBjb25zdCBhZGFwdGVyID0gY3R4LmNvbnRleHQuYWRhcHRlcjtcbiAgaWYgKCFhZGFwdGVyKSByZXR1cm4gbnVsbDtcbiAgdHJ5IHtcbiAgICBjb25zdCByb3cgPSBhd2FpdCBhZGFwdGVyLmZpbmRPbmUoe1xuICAgICAgbW9kZWw6IFwidXNlclwiLFxuICAgICAgc2VsZWN0OiBbXCJpZFwiLCBcIm5hbWVcIiwgXCJlbWFpbFwiXSxcbiAgICAgIHdoZXJlOiBbeyBmaWVsZCwgdmFsdWUgfV0sXG4gICAgfSk7XG4gICAgaWYgKCFyb3cpIHJldHVybiBudWxsO1xuICAgIHJldHVybiB7XG4gICAgICBpZDogU3RyaW5nKHJvdy5pZCksXG4gICAgICBuYW1lOiB0eXBlb2Ygcm93Lm5hbWUgPT09IFwic3RyaW5nXCIgPyByb3cubmFtZSA6IHVuZGVmaW5lZCxcbiAgICAgIGVtYWlsOiB0eXBlb2Ygcm93LmVtYWlsID09PSBcInN0cmluZ1wiID8gcm93LmVtYWlsIDogdW5kZWZpbmVkLFxuICAgIH07XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBudWxsO1xuICB9XG59O1xuXG5jb25zdCBpc05vbkVtcHR5U3RyaW5nID0gKHY6IHVua25vd24pOiB2IGlzIHN0cmluZyA9PiB0eXBlb2YgdiA9PT0gXCJzdHJpbmdcIiAmJiB2Lmxlbmd0aCA+IDA7XG5cbi8vIGRhc2gg7KCc6rGwIOyLnCDtlajqu5gg7IKs65287KeEIGxvY2F0aW9uIOqzteq4iSDqsr3roZzrpbwg64yA7LK07ZWc64ukLlxuLy8g7Jqw7ISg7Iic7JyEOiBjZi1jb25uZWN0aW5nLWlwID4geC1mb3J3YXJkZWQtZm9yKOyyqyDtla3rqqkpID4geC1yZWFsLWlwID4geC12ZXJjZWwtZm9yd2FyZGVkLWZvclxuLy8gKHNvbmFtdS50cyBJUF9IRUFERVJTIOyDgeyImOyZgCDrj5nsnbwpXG5jb25zdCBJUF9IRUFERVJfT1JERVIgPSBbXG4gIFwiY2YtY29ubmVjdGluZy1pcFwiLFxuICBcIngtZm9yd2FyZGVkLWZvclwiLFxuICBcIngtcmVhbC1pcFwiLFxuICBcIngtdmVyY2VsLWZvcndhcmRlZC1mb3JcIixcbl0gYXMgY29uc3Q7XG5cbmNvbnN0IHJlYWRIZWFkZXIgPSAoaGVhZGVyczogdW5rbm93biwga2V5OiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsID0+IHtcbiAgaWYgKCFoZWFkZXJzKSByZXR1cm4gbnVsbDtcbiAgaWYgKGhlYWRlcnMgaW5zdGFuY2VvZiBIZWFkZXJzKSB7XG4gICAgcmV0dXJuIGhlYWRlcnMuZ2V0KGtleSk7XG4gIH1cbiAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSBcIm9iamVjdFwiKSB7XG4gICAgY29uc3QgbWFwID0gaGVhZGVycyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICBjb25zdCB2ID0gbWFwW2tleV0gPz8gbWFwW2tleS50b0xvd2VyQ2FzZSgpXTtcbiAgICBpZiAodHlwZW9mIHYgPT09IFwic3RyaW5nXCIpIHJldHVybiB2O1xuICAgIGlmIChBcnJheS5pc0FycmF5KHYpICYmIHR5cGVvZiB2WzBdID09PSBcInN0cmluZ1wiKSByZXR1cm4gdlswXTtcbiAgfVxuICByZXR1cm4gbnVsbDtcbn07XG5cbmNvbnN0IGV4dHJhY3RMb2NhdGlvbkZyb21IZWFkZXJzID0gKGhlYWRlcnM6IHVua25vd24pOiBCdWlsZGVyTG9jYXRpb24gPT4ge1xuICBsZXQgaXBBZGRyZXNzOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgZm9yIChjb25zdCBrZXkgb2YgSVBfSEVBREVSX09SREVSKSB7XG4gICAgY29uc3QgcmF3ID0gcmVhZEhlYWRlcihoZWFkZXJzLCBrZXkpO1xuICAgIGlmICh0eXBlb2YgcmF3ID09PSBcInN0cmluZ1wiICYmIHJhdy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBmaXJzdCA9IHJhdy5zcGxpdChcIixcIilbMF0/LnRyaW0oKTtcbiAgICAgIGlmIChmaXJzdCkge1xuICAgICAgICBpcEFkZHJlc3MgPSBmaXJzdDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGNvbnN0IGNvdW50cnlDb2RlID0gcmVhZEhlYWRlcihoZWFkZXJzLCBcImNmLWlwY291bnRyeVwiKTtcbiAgY29uc3QgY2l0eSA9IHJlYWRIZWFkZXIoaGVhZGVycywgXCJjZi1pcGNpdHlcIik7XG4gIHJldHVybiB7XG4gICAgaXBBZGRyZXNzOiBpcEFkZHJlc3MgPz8gdW5kZWZpbmVkLFxuICAgIGNpdHk6IGNpdHkgPz8gdW5kZWZpbmVkLFxuICAgIGNvdW50cnk6IHVuZGVmaW5lZCxcbiAgICBjb3VudHJ5Q29kZTogY291bnRyeUNvZGUgPz8gdW5kZWZpbmVkLFxuICB9O1xufTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gT3JnYW5pemF0aW9uIGhvb2sg656Y7ZWRIO2XrO2NvFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxudHlwZSBPcmdIb29rRm4gPSAoLi4uYXJnczogdW5rbm93bltdKSA9PiBQcm9taXNlPHVua25vd24+O1xuXG4vLyDso7zslrTsp4Qgb3JnYW5pemF0aW9uSG9va3Mg66CI7L2U65Oc7JeQIOuMgO2VtCDtlbTri7kgbmFtZeydmCDquLDsobQgaG9va+ydhCBjaGFpbu2VnOuLpC5cbi8vIGhhbmRsZXLripQgcGF5bG9hZCDqsJ3ssrQo7LKrIOuyiOynuCDsnbjsnpAp66eMIOuwm+yVhOyEnCBhdWRpdCBlbWl07J2EIOyImO2Wie2VnOuLpC5cbmNvbnN0IHdyYXBPcmdIb29rID0gPFBheWxvYWQ+KFxuICBob29rczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIG5hbWU6IHN0cmluZyxcbiAgaGFuZGxlcjogKHBheWxvYWQ6IFBheWxvYWQpID0+IFByb21pc2U8dm9pZD4sXG4pOiB2b2lkID0+IHtcbiAgY29uc3QgcHJldiA9IGhvb2tzW25hbWVdIGFzIE9yZ0hvb2tGbiB8IHVuZGVmaW5lZDtcbiAgaG9va3NbbmFtZV0gPSBhc3luYyAoLi4uYXJnczogdW5rbm93bltdKTogUHJvbWlzZTx1bmtub3duPiA9PiB7XG4gICAgYXdhaXQgaGFuZGxlcihhcmdzWzBdIGFzIFBheWxvYWQpO1xuICAgIGlmIChwcmV2KSByZXR1cm4gcHJldiguLi5hcmdzKTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9O1xufTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUGx1Z2luIGVudHJ5XG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vKipcbiAqIEJldHRlciBBdXRoIGRhdGFiYXNlSG9va3Mvb3JnYW5pemF0aW9uSG9va3MvbWlkZGxld2FyZeyXkOyEnCDsiJjsp5HtlZxcbiAqIOydtOuypO2KuOulvCBgREIuZ2V0REIoXCJ3XCIpYOuhnCDslrvsnYAga25leOyXkCBgaW5nZXN0QXVkaXRFdmVudGDroZwg7KCB7J6s7ZWc64ukLlxuICpcbiAqIC0gZGFzaChAYmV0dGVyLWF1dGgvaW5mcmEp7J2YIGF1ZGl0LWV2ZW50IOyImOynkSDtm4Ug6rWs7KGw66W8IOywuOqzoO2VtCBTb25hbXUg64K067aAIOyggeyerCDqsr3roZzroZwg7Y+s7YyF7ZWc64ukLlxuICogLSBkYXNo7J2YIGluZnJhIOyXsOqysC9BUEkgZW5kcG9pbnQg7KCc6rO1IOuylOychOuKlCDtj6ztlajtlZjsp4Ag7JWK6rOgLCBhdWRpdC1ldmVudCBlbWl0L2luZ2VzdCDqsr3roZzrp4wg7Jyg7KeA7ZWc64ukLlxuICogLSBzZWN1cml0eSA07KKF7J2AIFIxIOqysOygleyXkCDrlLDrnbwgc2NvcGUgb3V0IChidWlsZGVycy50c+ydmCBUT0RPIOyjvOyEnSDssLjsobApLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc29uYW11QXVkaXRMb2coKTogQmV0dGVyQXV0aFBsdWdpbiB7XG4gIGNvbnN0IGxvZ2dlciA9IGdldExvZ2dlcihbXCJzb25hbXVcIiwgXCJhdWRpdC1sb2dcIl0pO1xuICBjb25zdCBjYXRhbG9nID0gYnVpbGRBdWRpdEV2ZW50Q2F0YWxvZygpO1xuXG4gIC8vIGRhc2ggNzM5NDog64+Z7J28IOyalOyyreyXkOyEnCDshLjshZgg67KM7YGsIOyCreygnOqwgCDri6Ttmowg67Cc7IOd7ZWgIOuVjCBhbGxfc2Vzc2lvbnNfcmV2b2tlZOulvFxuICAvLyDtlZwg67KI66eMIGVtaXTtlZjrj4TroZ0g7LKY66asIOy7qO2FjeyKpO2KuOulvCDquLDslrXtlZzri6QuXG4gIGNvbnN0IHByb2Nlc3NlZEJ1bGtPcGVyYXRpb25Db250ZXh0cyA9IG5ldyBXZWFrU2V0PG9iamVjdD4oKTtcblxuICBjb25zdCBlbWl0ID0gYXN5bmMgKGV2ZW50OiBBdWRpdExvZ0V2ZW50KTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGluZ2VzdEF1ZGl0RXZlbnQoREIuZ2V0REIoXCJ3XCIpLCBldmVudCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoXCJhdWRpdCBldmVudCBpbmdlc3QgZmFpbGVkOiB7ZXJyb3J9XCIsIHsgZXJyb3I6IGVyciB9KTtcbiAgICB9XG4gIH07XG5cbiAgLy8gY3R4LnBhdGggKyBzZXNzaW9u7JeQ7IScIOyCrOyaqeyekCDtirjrpqzqsbDrpbwg64+E7Lac7ZWc64ukKGVudGl0eS5pZOulvCBzdWJqZWN066GcIOyCrOyaqSkuXG4gIGNvbnN0IHRyaWdnZXJGb3IgPSAoY3R4OiBCZXR0ZXJBdXRoUmVxdWVzdEN0eCwgc3ViamVjdFVzZXJJZDogc3RyaW5nKTogQnVpbGRlclRyaWdnZXIgPT5cbiAgICBnZXRUcmlnZ2VySW5mbyhjdHgucGF0aCwgY3R4LmNvbnRleHQuc2Vzc2lvbj8uc2Vzc2lvbj8udXNlcklkID8/IG51bGwsIHN1YmplY3RVc2VySWQpO1xuXG4gIGNvbnN0IGxvY2F0aW9uRm9yID0gKGN0eDogQmV0dGVyQXV0aFJlcXVlc3RDdHgpOiBCdWlsZGVyTG9jYXRpb24gfCB1bmRlZmluZWQgPT5cbiAgICBjdHguY29udGV4dC5sb2NhdGlvbiA/PyB1bmRlZmluZWQ7XG5cbiAgcmV0dXJuIHtcbiAgICBpZDogXCJzb25hbXUtYXVkaXQtbG9nXCIsXG5cbiAgICBpbml0KHBsdWdpbkN0eDogdW5rbm93bikge1xuICAgICAgaW5zdGFsbE9yZ2FuaXphdGlvbkhvb2tzKHBsdWdpbkN0eCwgY2F0YWxvZywgZW1pdCwgbG9nZ2VyKTtcblxuICAgICAgLy8gZGFzaCA3MjgzLTc0NDkg66+465+sOiBkYXRhYmFzZUhvb2tzICh1c2VyL3Nlc3Npb24vYWNjb3VudC92ZXJpZmljYXRpb24pLlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgIGRhdGFiYXNlSG9va3M6IHtcbiAgICAgICAgICAgIHVzZXI6IHtcbiAgICAgICAgICAgICAgY3JlYXRlOiB7XG4gICAgICAgICAgICAgICAgYWZ0ZXI6IGFzeW5jIChyYXdVc2VyOiB1bmtub3duLCByYXdDdHg/OiB1bmtub3duKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBjdHggPSBuYXJyb3dSZXF1ZXN0Q3R4KHJhd0N0eCk7XG4gICAgICAgICAgICAgICAgICBpZiAoIWN0eCkgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgY29uc3QgdXNlciA9IHJhd1VzZXIgYXMgVXNlclNuYXBzaG90O1xuICAgICAgICAgICAgICAgICAgYXdhaXQgZW1pdChcbiAgICAgICAgICAgICAgICAgICAgY2F0YWxvZy51c2VyLnRyYWNrVXNlclNpZ25lZFVwKFxuICAgICAgICAgICAgICAgICAgICAgIHVzZXIsXG4gICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckZvcihjdHgsIHVzZXIuaWQpLFxuICAgICAgICAgICAgICAgICAgICAgIGxvY2F0aW9uRm9yKGN0eCksXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHVwZGF0ZToge1xuICAgICAgICAgICAgICAgIGFmdGVyOiBhc3luYyAocmF3VXNlcjogdW5rbm93biwgcmF3Q3R4PzogdW5rbm93bik6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgICAgICAgY29uc3QgY3R4ID0gbmFycm93UmVxdWVzdEN0eChyYXdDdHgpO1xuICAgICAgICAgICAgICAgICAgaWYgKCFjdHgpIHJldHVybjtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHVzZXIgPSByYXdVc2VyIGFzIFVzZXJTbmFwc2hvdCAmIHtcbiAgICAgICAgICAgICAgICAgICAgZW1haWxWZXJpZmllZD86IGJvb2xlYW47XG4gICAgICAgICAgICAgICAgICAgIGltYWdlPzogc3RyaW5nIHwgbnVsbDtcbiAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICBjb25zdCBwYXRoID0gY3R4LnBhdGg7XG4gICAgICAgICAgICAgICAgICBjb25zdCB0cmlnZ2VyID0gdHJpZ2dlckZvcihjdHgsIHVzZXIuaWQpO1xuICAgICAgICAgICAgICAgICAgY29uc3QgbG9jYXRpb24gPSBsb2NhdGlvbkZvcihjdHgpO1xuXG4gICAgICAgICAgICAgICAgICBpZiAobWF0Y2hlc0FueVJvdXRlKHBhdGgsIFtST1VURVMuVVBEQVRFX1VTRVIsIFJPVVRFUy5EQVNIX1VQREFURV9VU0VSXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdXBkYXRlZEZpZWxkcyA9IE9iamVjdC5rZXlzKChjdHguYm9keSBhcyBvYmplY3QpID8/IHt9KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNPbmx5SW1hZ2VVcGRhdGUgPVxuICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZWRGaWVsZHMubGVuZ3RoID09PSAxICYmIHVwZGF0ZWRGaWVsZHNbMF0gPT09IFwiaW1hZ2VcIjtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNPbmx5RW1haWxWZXJpZmllZFVwZGF0ZSA9XG4gICAgICAgICAgICAgICAgICAgICAgdXBkYXRlZEZpZWxkcy5sZW5ndGggPT09IDEgJiYgdXBkYXRlZEZpZWxkc1swXSA9PT0gXCJlbWFpbFZlcmlmaWVkXCI7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGhhc0VtYWlsVmVyaWZpZWRVcGRhdGUgPSB1cGRhdGVkRmllbGRzLmluY2x1ZGVzKFwiZW1haWxWZXJpZmllZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzT25seUVtYWlsVmVyaWZpZWRVcGRhdGUgJiYgdXNlci5lbWFpbFZlcmlmaWVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgYXdhaXQgZW1pdChjYXRhbG9nLnVzZXIudHJhY2tVc2VyRW1haWxWZXJpZmllZCh1c2VyLCB0cmlnZ2VyLCBsb2NhdGlvbikpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT25seUltYWdlVXBkYXRlICYmIHVzZXIuaW1hZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBlbWl0KFxuICAgICAgICAgICAgICAgICAgICAgICAgY2F0YWxvZy51c2VyLnRyYWNrVXNlclByb2ZpbGVJbWFnZVVwZGF0ZWQodXNlciwgdHJpZ2dlciwgbG9jYXRpb24pLFxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzT25seUltYWdlVXBkYXRlICYmICFpc09ubHlFbWFpbFZlcmlmaWVkVXBkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgYXdhaXQgZW1pdChcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhdGFsb2cudXNlci50cmFja1VzZXJQcm9maWxlVXBkYXRlZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlZEZpZWxkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKGhhc0VtYWlsVmVyaWZpZWRVcGRhdGUgJiYgdXNlci5lbWFpbFZlcmlmaWVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBlbWl0KGNhdGFsb2cudXNlci50cmFja1VzZXJFbWFpbFZlcmlmaWVkKHVzZXIsIHRyaWdnZXIsIGxvY2F0aW9uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1hdGNoZXNBbnlSb3V0ZShwYXRoLCBbUk9VVEVTLkNIQU5HRV9FTUFJTF0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHVwZGF0ZWRGaWVsZHMgPSBPYmplY3Qua2V5cygoY3R4LmJvZHkgYXMgb2JqZWN0KSA/PyB7fSk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgICAgICAgICAgICAgICAgY2F0YWxvZy51c2VyLnRyYWNrVXNlclByb2ZpbGVVcGRhdGVkKHVzZXIsIHVwZGF0ZWRGaWVsZHMsIHRyaWdnZXIsIGxvY2F0aW9uKSxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGlmIChtYXRjaGVzQW55Um91dGUocGF0aCwgW1JPVVRFUy5WRVJJRllfRU1BSUxdKSAmJiB1c2VyLmVtYWlsVmVyaWZpZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgZW1pdChjYXRhbG9nLnVzZXIudHJhY2tVc2VyRW1haWxWZXJpZmllZCh1c2VyLCB0cmlnZ2VyLCBsb2NhdGlvbikpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICBtYXRjaGVzQW55Um91dGUocGF0aCwgW1JPVVRFUy5BRE1JTl9CQU5fVVNFUl0pICYmXG4gICAgICAgICAgICAgICAgICAgIFwiYmFubmVkXCIgaW4gdXNlciAmJlxuICAgICAgICAgICAgICAgICAgICB1c2VyLmJhbm5lZFxuICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoY2F0YWxvZy51c2VyLnRyYWNrVXNlckJhbm5lZCh1c2VyLCB0cmlnZ2VyLCBsb2NhdGlvbikpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICBtYXRjaGVzQW55Um91dGUocGF0aCwgW1JPVVRFUy5BRE1JTl9VTkJBTl9VU0VSXSkgJiZcbiAgICAgICAgICAgICAgICAgICAgXCJiYW5uZWRcIiBpbiB1c2VyICYmXG4gICAgICAgICAgICAgICAgICAgICF1c2VyLmJhbm5lZFxuICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoY2F0YWxvZy51c2VyLnRyYWNrVXNlclVuQmFubmVkKHVzZXIsIHRyaWdnZXIsIGxvY2F0aW9uKSk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZGVsZXRlOiB7XG4gICAgICAgICAgICAgICAgYWZ0ZXI6IGFzeW5jIChyYXdVc2VyOiB1bmtub3duLCByYXdDdHg/OiB1bmtub3duKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBjdHggPSBuYXJyb3dSZXF1ZXN0Q3R4KHJhd0N0eCk7XG4gICAgICAgICAgICAgICAgICBpZiAoIWN0eCkgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgY29uc3QgdXNlciA9IHJhd1VzZXIgYXMgVXNlclNuYXBzaG90O1xuICAgICAgICAgICAgICAgICAgYXdhaXQgZW1pdChcbiAgICAgICAgICAgICAgICAgICAgY2F0YWxvZy51c2VyLnRyYWNrVXNlckRlbGV0ZWQodXNlciwgdHJpZ2dlckZvcihjdHgsIHVzZXIuaWQpLCBsb2NhdGlvbkZvcihjdHgpKSxcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXNzaW9uOiB7XG4gICAgICAgICAgICAgIGNyZWF0ZToge1xuICAgICAgICAgICAgICAgIGJlZm9yZTogYXN5bmMgKFxuICAgICAgICAgICAgICAgICAgcmF3U2Vzc2lvbjogdW5rbm93bixcbiAgICAgICAgICAgICAgICAgIHJhd0N0eD86IHVua25vd24sXG4gICAgICAgICAgICAgICAgKTogUHJvbWlzZTx7IGRhdGE6IHsgbG9naW5NZXRob2Q6IHN0cmluZyB8IG51bGwgfSB9IHwgdW5kZWZpbmVkPiA9PiB7XG4gICAgICAgICAgICAgICAgICB2b2lkIHJhd1Nlc3Npb247XG4gICAgICAgICAgICAgICAgICBjb25zdCBjdHggPSBuYXJyb3dSZXF1ZXN0Q3R4KHJhd0N0eCk7XG4gICAgICAgICAgICAgICAgICBpZiAoIWN0eCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgIHJldHVybiB7IGRhdGE6IHsgbG9naW5NZXRob2Q6IGdldExvZ2luTWV0aG9kKGN0eC5wYXRoLCBjdHgucGFyYW1zPy5pZCkgfSB9O1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYWZ0ZXI6IGFzeW5jIChyYXdTZXNzaW9uOiB1bmtub3duLCByYXdDdHg/OiB1bmtub3duKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBjdHggPSBuYXJyb3dSZXF1ZXN0Q3R4KHJhd0N0eCk7XG4gICAgICAgICAgICAgICAgICBpZiAoIWN0eCkgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IHJhd1Nlc3Npb24gYXMgU2Vzc2lvblNuYXBzaG90O1xuICAgICAgICAgICAgICAgICAgaWYgKCFzZXNzaW9uLnVzZXJJZCkgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgY29uc3QgbG9jYXRpb24gPSBsb2NhdGlvbkZvcihjdHgpO1xuICAgICAgICAgICAgICAgICAgY29uc3QgbG9naW5NZXRob2QgPSBnZXRMb2dpbk1ldGhvZChjdHgucGF0aCwgY3R4LnBhcmFtcz8uaWQpID8/IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGVucmljaGVkU2Vzc2lvbjogU2Vzc2lvblNuYXBzaG90ID0ge1xuICAgICAgICAgICAgICAgICAgICAuLi5zZXNzaW9uLFxuICAgICAgICAgICAgICAgICAgICBsb2dpbk1ldGhvZDogbG9naW5NZXRob2QgPz8gc2Vzc2lvbi5sb2dpbk1ldGhvZCA/PyBudWxsLFxuICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHVzZXIgPSBhd2FpdCBmZXRjaFVzZXJCeShjdHgsIFwiaWRcIiwgc2Vzc2lvbi51c2VySWQpO1xuXG4gICAgICAgICAgICAgICAgICBsZXQgdHJpZ2dlcjogQnVpbGRlclRyaWdnZXI7XG4gICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIG1hdGNoZXNBbnlSb3V0ZShjdHgucGF0aCwgW1xuICAgICAgICAgICAgICAgICAgICAgIFJPVVRFUy5TSUdOX0lOLFxuICAgICAgICAgICAgICAgICAgICAgIFJPVVRFUy5TSUdOX1VQLFxuICAgICAgICAgICAgICAgICAgICAgIFJPVVRFUy5TSUdOX0lOX1NPQ0lBTF9DQUxMQkFDSyxcbiAgICAgICAgICAgICAgICAgICAgICBST1VURVMuU0lHTl9JTl9PQVVUSF9DQUxMQkFDSyxcbiAgICAgICAgICAgICAgICAgICAgXSlcbiAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyID0gZ2V0VHJpZ2dlckluZm8oY3R4LnBhdGgsIHNlc3Npb24udXNlcklkLCBzZXNzaW9uLnVzZXJJZCk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgICAgICAgICAgICAgICAgY2F0YWxvZy5zZXNzaW9uLnRyYWNrVXNlclNpZ25lZEluKGVucmljaGVkU2Vzc2lvbiwgdXNlciwgdHJpZ2dlciwgbG9jYXRpb24pLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlciA9IHRyaWdnZXJGb3IoY3R4LCBzZXNzaW9uLnVzZXJJZCk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBhd2FpdCBlbWl0KFxuICAgICAgICAgICAgICAgICAgICBjYXRhbG9nLnNlc3Npb24udHJhY2tTZXNzaW9uQ3JlYXRlZChlbnJpY2hlZFNlc3Npb24sIHVzZXIsIHRyaWdnZXIsIGxvY2F0aW9uKSxcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICBpZiAoaXNOb25FbXB0eVN0cmluZyhzZXNzaW9uLmltcGVyc29uYXRlZEJ5KSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpbXBlcnNvbmF0b3IgPSBhd2FpdCBmZXRjaFVzZXJCeShjdHgsIFwiaWRcIiwgc2Vzc2lvbi5pbXBlcnNvbmF0ZWRCeSk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgICAgICAgICAgICAgICAgY2F0YWxvZy5zZXNzaW9uLnRyYWNrVXNlckltcGVyc29uYXRlZChcbiAgICAgICAgICAgICAgICAgICAgICAgIGVucmljaGVkU2Vzc2lvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHVzZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbXBlcnNvbmF0b3IsXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRyaWdnZXJlZEJ5OiBzZXNzaW9uLmltcGVyc29uYXRlZEJ5LFxuICAgICAgICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyQ29udGV4dDogdHJpZ2dlci50cmlnZ2VyQ29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBsb2NhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGRlbGV0ZToge1xuICAgICAgICAgICAgICAgIGFmdGVyOiBhc3luYyAocmF3U2Vzc2lvbjogdW5rbm93biwgcmF3Q3R4PzogdW5rbm93bik6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgICAgICAgY29uc3QgY3R4ID0gbmFycm93UmVxdWVzdEN0eChyYXdDdHgpO1xuICAgICAgICAgICAgICAgICAgaWYgKCFjdHgpIHJldHVybjtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb24gPSByYXdTZXNzaW9uIGFzIFNlc3Npb25TbmFwc2hvdDtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2F0aW9uID0gbG9jYXRpb25Gb3IoY3R4KTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGVucmljaGVkU2Vzc2lvbjogU2Vzc2lvblNuYXBzaG90ID0geyAuLi5zZXNzaW9uIH07XG4gICAgICAgICAgICAgICAgICBjb25zdCB1c2VyID0gYXdhaXQgZmV0Y2hVc2VyQnkoY3R4LCBcImlkXCIsIHNlc3Npb24udXNlcklkKTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHRyaWdnZXIgPSB0cmlnZ2VyRm9yKGN0eCwgc2Vzc2lvbi51c2VySWQpO1xuICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICBtYXRjaGVzQW55Um91dGUoY3R4LnBhdGgsIFtcbiAgICAgICAgICAgICAgICAgICAgICBST1VURVMuUkVWT0tFX0FMTF9TRVNTSU9OUyxcbiAgICAgICAgICAgICAgICAgICAgICBST1VURVMuQURNSU5fUkVWT0tFX1VTRVJfU0VTU0lPTlMsXG4gICAgICAgICAgICAgICAgICAgICAgUk9VVEVTLkRBU0hfUkVWT0tFX1NFU1NJT05TX0FMTCxcbiAgICAgICAgICAgICAgICAgICAgICBST1VURVMuREFTSF9CQU5fVVNFUixcbiAgICAgICAgICAgICAgICAgICAgXSlcbiAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXByb2Nlc3NlZEJ1bGtPcGVyYXRpb25Db250ZXh0cy5oYXMoY3R4KSkge1xuICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXRhbG9nLnNlc3Npb24udHJhY2tTZXNzaW9uUmV2b2tlZEFsbChlbnJpY2hlZFNlc3Npb24sIHVzZXIsIHRyaWdnZXIpLFxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc2VkQnVsa09wZXJhdGlvbkNvbnRleHRzLmFkZChjdHgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1hdGNoZXNBbnlSb3V0ZShjdHgucGF0aCwgW1JPVVRFUy5TSUdOX09VVF0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgICAgICAgICAgICAgICAgY2F0YWxvZy5zZXNzaW9uLnRyYWNrVXNlclNpZ25lZE91dChlbnJpY2hlZFNlc3Npb24sIHVzZXIsIHRyaWdnZXIsIGxvY2F0aW9uKSxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgICAgICAgICAgICAgICAgY2F0YWxvZy5zZXNzaW9uLnRyYWNrU2Vzc2lvblJldm9rZWQoZW5yaWNoZWRTZXNzaW9uLCB1c2VyLCB0cmlnZ2VyLCBsb2NhdGlvbiksXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAoaXNOb25FbXB0eVN0cmluZyhzZXNzaW9uLmltcGVyc29uYXRlZEJ5KSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpbXBlcnNvbmF0b3IgPSBhd2FpdCBmZXRjaFVzZXJCeShjdHgsIFwiaWRcIiwgc2Vzc2lvbi5pbXBlcnNvbmF0ZWRCeSk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgICAgICAgICAgICAgICAgY2F0YWxvZy5zZXNzaW9uLnRyYWNrVXNlckltcGVyc29uYXRpb25TdG9wKFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5yaWNoZWRTZXNzaW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgdXNlcixcbiAgICAgICAgICAgICAgICAgICAgICAgIGltcGVyc29uYXRvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyaWdnZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBsb2NhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYWNjb3VudDoge1xuICAgICAgICAgICAgICBjcmVhdGU6IHtcbiAgICAgICAgICAgICAgICBhZnRlcjogYXN5bmMgKHJhd0FjY291bnQ6IHVua25vd24sIHJhd0N0eD86IHVua25vd24pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IG5hcnJvd1JlcXVlc3RDdHgocmF3Q3R4KTtcbiAgICAgICAgICAgICAgICAgIGlmICghY3R4KSByZXR1cm47XG4gICAgICAgICAgICAgICAgICBjb25zdCBhY2NvdW50ID0gcmF3QWNjb3VudCBhcyBBY2NvdW50U25hcHNob3Q7XG4gICAgICAgICAgICAgICAgICBpZiAoIWFjY291bnQudXNlcklkKSByZXR1cm47XG4gICAgICAgICAgICAgICAgICBjb25zdCB1c2VyID0gYXdhaXQgZmV0Y2hVc2VyQnkoY3R4LCBcImlkXCIsIGFjY291bnQudXNlcklkKTtcbiAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgICAgICAgICAgICAgIGNhdGFsb2cuYWNjb3VudC50cmFja0FjY291bnRMaW5raW5nKFxuICAgICAgICAgICAgICAgICAgICAgIGFjY291bnQsXG4gICAgICAgICAgICAgICAgICAgICAgdXNlcixcbiAgICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyRm9yKGN0eCwgYWNjb3VudC51c2VySWQpLFxuICAgICAgICAgICAgICAgICAgICAgIGxvY2F0aW9uRm9yKGN0eCksXG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHVwZGF0ZToge1xuICAgICAgICAgICAgICAgIGFmdGVyOiBhc3luYyAocmF3QWNjb3VudDogdW5rbm93biwgcmF3Q3R4PzogdW5rbm93bik6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgICAgICAgY29uc3QgY3R4ID0gbmFycm93UmVxdWVzdEN0eChyYXdDdHgpO1xuICAgICAgICAgICAgICAgICAgaWYgKCFjdHgpIHJldHVybjtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGFjY291bnQgPSByYXdBY2NvdW50IGFzIEFjY291bnRTbmFwc2hvdDtcbiAgICAgICAgICAgICAgICAgIGlmICghYWNjb3VudC51c2VySWQpIHJldHVybjtcbiAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgIW1hdGNoZXNBbnlSb3V0ZShjdHgucGF0aCwgW1xuICAgICAgICAgICAgICAgICAgICAgIFJPVVRFUy5DSEFOR0VfUEFTU1dPUkQsXG4gICAgICAgICAgICAgICAgICAgICAgUk9VVEVTLlNFVF9QQVNTV09SRCxcbiAgICAgICAgICAgICAgICAgICAgICBST1VURVMuUkVTRVRfUEFTU1dPUkQsXG4gICAgICAgICAgICAgICAgICAgICAgUk9VVEVTLkFETUlOX1NFVF9QQVNTV09SRCxcbiAgICAgICAgICAgICAgICAgICAgXSlcbiAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBjb25zdCB1c2VyID0gYXdhaXQgZmV0Y2hVc2VyQnkoY3R4LCBcImlkXCIsIGFjY291bnQudXNlcklkKTtcbiAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgICAgICAgICAgICAgIGNhdGFsb2cuYWNjb3VudC50cmFja0FjY291bnRQYXNzd29yZENoYW5nZShcbiAgICAgICAgICAgICAgICAgICAgICBhY2NvdW50LFxuICAgICAgICAgICAgICAgICAgICAgIHVzZXIsXG4gICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckZvcihjdHgsIGFjY291bnQudXNlcklkKSxcbiAgICAgICAgICAgICAgICAgICAgICBsb2NhdGlvbkZvcihjdHgpLFxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBkZWxldGU6IHtcbiAgICAgICAgICAgICAgICBhZnRlcjogYXN5bmMgKHJhd0FjY291bnQ6IHVua25vd24sIHJhd0N0eD86IHVua25vd24pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IG5hcnJvd1JlcXVlc3RDdHgocmF3Q3R4KTtcbiAgICAgICAgICAgICAgICAgIGlmICghY3R4KSByZXR1cm47XG4gICAgICAgICAgICAgICAgICBjb25zdCBhY2NvdW50ID0gcmF3QWNjb3VudCBhcyBBY2NvdW50U25hcHNob3Q7XG4gICAgICAgICAgICAgICAgICBpZiAoIWFjY291bnQudXNlcklkKSByZXR1cm47XG4gICAgICAgICAgICAgICAgICBjb25zdCB1c2VyID0gYXdhaXQgZmV0Y2hVc2VyQnkoY3R4LCBcImlkXCIsIGFjY291bnQudXNlcklkKTtcbiAgICAgICAgICAgICAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgICAgICAgICAgICAgIGNhdGFsb2cuYWNjb3VudC50cmFja0FjY291bnRVbmxpbmsoXG4gICAgICAgICAgICAgICAgICAgICAgYWNjb3VudCxcbiAgICAgICAgICAgICAgICAgICAgICB1c2VyLFxuICAgICAgICAgICAgICAgICAgICAgIHRyaWdnZXJGb3IoY3R4LCBhY2NvdW50LnVzZXJJZCksXG4gICAgICAgICAgICAgICAgICAgICAgbG9jYXRpb25Gb3IoY3R4KSxcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2ZXJpZmljYXRpb246IHtcbiAgICAgICAgICAgICAgY3JlYXRlOiB7XG4gICAgICAgICAgICAgICAgYWZ0ZXI6IGFzeW5jIChyYXdWZXJpZmljYXRpb246IHVua25vd24sIHJhd0N0eD86IHVua25vd24pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IG5hcnJvd1JlcXVlc3RDdHgocmF3Q3R4KTtcbiAgICAgICAgICAgICAgICAgIGlmICghY3R4KSByZXR1cm47XG4gICAgICAgICAgICAgICAgICBpZiAoIW1hdGNoZXNBbnlSb3V0ZShjdHgucGF0aCwgW1JPVVRFUy5SRVFVRVNUX1BBU1NXT1JEX1JFU0VUXSkpIHJldHVybjtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHJhd1ZlcmlmaWNhdGlvbiBhcyBWZXJpZmljYXRpb25TbmFwc2hvdDtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb25Vc2VySWQgPSBjdHguY29udGV4dC5zZXNzaW9uPy51c2VyPy5pZCA/PyBcInVua25vd25cIjtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHRyaWdnZXIgPSBnZXRUcmlnZ2VySW5mbyhjdHgucGF0aCwgc2Vzc2lvblVzZXJJZCwgc2Vzc2lvblVzZXJJZCk7XG4gICAgICAgICAgICAgICAgICBjb25zdCB1c2VyID0gYXdhaXQgZmV0Y2hVc2VyQnkoY3R4LCBcImlkXCIsIHZlcmlmaWNhdGlvbi52YWx1ZSk7XG4gICAgICAgICAgICAgICAgICBhd2FpdCBlbWl0KFxuICAgICAgICAgICAgICAgICAgICBjYXRhbG9nLnZlcmlmaWNhdGlvbi50cmFja1Bhc3N3b3JkUmVzZXRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICAgICAgIHZlcmlmaWNhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICB1c2VyLFxuICAgICAgICAgICAgICAgICAgICAgIHRyaWdnZXIsXG4gICAgICAgICAgICAgICAgICAgICAgbG9jYXRpb25Gb3IoY3R4KSxcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZGVsZXRlOiB7XG4gICAgICAgICAgICAgICAgYWZ0ZXI6IGFzeW5jIChyYXdWZXJpZmljYXRpb246IHVua25vd24sIHJhd0N0eD86IHVua25vd24pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IG5hcnJvd1JlcXVlc3RDdHgocmF3Q3R4KTtcbiAgICAgICAgICAgICAgICAgIGlmICghY3R4KSByZXR1cm47XG4gICAgICAgICAgICAgICAgICBpZiAoIW1hdGNoZXNBbnlSb3V0ZShjdHgucGF0aCwgW1JPVVRFUy5SRVNFVF9QQVNTV09SRF0pKSByZXR1cm47XG4gICAgICAgICAgICAgICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSByYXdWZXJpZmljYXRpb24gYXMgVmVyaWZpY2F0aW9uU25hcHNob3Q7XG4gICAgICAgICAgICAgICAgICBjb25zdCBzZXNzaW9uVXNlcklkID0gY3R4LmNvbnRleHQuc2Vzc2lvbj8udXNlcj8uaWQgPz8gXCJ1bmtub3duXCI7XG4gICAgICAgICAgICAgICAgICBjb25zdCB0cmlnZ2VyID0gZ2V0VHJpZ2dlckluZm8oY3R4LnBhdGgsIHNlc3Npb25Vc2VySWQsIHNlc3Npb25Vc2VySWQpO1xuICAgICAgICAgICAgICAgICAgY29uc3QgdXNlciA9IGF3YWl0IGZldGNoVXNlckJ5KGN0eCwgXCJpZFwiLCB2ZXJpZmljYXRpb24udmFsdWUpO1xuICAgICAgICAgICAgICAgICAgYXdhaXQgZW1pdChcbiAgICAgICAgICAgICAgICAgICAgY2F0YWxvZy52ZXJpZmljYXRpb24udHJhY2tQYXNzd29yZFJlc2V0UmVxdWVzdENvbXBsZXRpb24oXG4gICAgICAgICAgICAgICAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgIHVzZXIsXG4gICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlcixcbiAgICAgICAgICAgICAgICAgICAgICBsb2NhdGlvbkZvcihjdHgpLFxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9LFxuXG4gICAgaG9va3M6IHtcbiAgICAgIGJlZm9yZTogW1xuICAgICAgICB7XG4gICAgICAgICAgLy8gZGFzaCDsoJzqsbDroZwg7IKs65287KeEIGxvY2F0aW9uIOqzteq4iSDqsr3roZzrpbwg67O16rWs7ZWc64ukLlxuICAgICAgICAgIC8vIOuqqOuToCDsmpTssq3sl5DshJwgY3R4LmNvbnRleHQubG9jYXRpb27snYQg7LGE7JuMIOydtO2bhCDruYzrjZTrk6TsnbQgaXBBZGRyZXNzL2NpdHkvY291bnRyeUNvZGXrpbwg6riw66Gd7ZWgIOyImCDsnojqsowg7ZWc64ukLlxuICAgICAgICAgIG1hdGNoZXI6ICgpID0+IHRydWUsXG4gICAgICAgICAgaGFuZGxlcjogY3JlYXRlQXV0aE1pZGRsZXdhcmUoYXN5bmMgKHJhd0N0eCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY3R4ID0gcmF3Q3R4IGFzIHtcbiAgICAgICAgICAgICAgaGVhZGVycz86IHVua25vd247XG4gICAgICAgICAgICAgIHJlcXVlc3Q/OiB7IGhlYWRlcnM/OiB1bmtub3duIH0gfCB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgIGNvbnRleHQ/OiB7IGxvY2F0aW9uPzogQnVpbGRlckxvY2F0aW9uIHwgbnVsbCB9ICYgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKCFjdHguY29udGV4dCkgcmV0dXJuO1xuICAgICAgICAgICAgY29uc3QgaGVhZGVycyA9IGN0eC5oZWFkZXJzID8/IGN0eC5yZXF1ZXN0Py5oZWFkZXJzO1xuICAgICAgICAgICAgY3R4LmNvbnRleHQubG9jYXRpb24gPSBleHRyYWN0TG9jYXRpb25Gcm9tSGVhZGVycyhoZWFkZXJzKTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBhZnRlcjogW1xuICAgICAgICB7XG4gICAgICAgICAgLy8gZGFzaCA3NDYyLTc0ODcg66+465+sOiB2ZXJpZmljYXRpb24gZW1haWwgc2VuZCwgc2lnbi1pbiBhdHRlbXB0cy5cbiAgICAgICAgICAvLyBHRVQg7JqU7LKt7J2AIOy9nOuwsSDqsr3roZzrp4wg7Ya16rO87Iuc7YKo64ukLlxuICAgICAgICAgIG1hdGNoZXI6IChjdHg6IHVua25vd24pOiBib29sZWFuID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGMgPSBjdHggYXMgeyByZXF1ZXN0PzogeyBtZXRob2Q/OiBzdHJpbmc7IHVybD86IHN0cmluZyB9IH07XG4gICAgICAgICAgICBpZiAoYy5yZXF1ZXN0Py5tZXRob2QgIT09IFwiR0VUXCIpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgaWYgKCFjLnJlcXVlc3QudXJsKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCBwID0gbmV3IFVSTChjLnJlcXVlc3QudXJsKS5wYXRobmFtZTtcbiAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXNBbnlSb3V0ZShwLCBbXG4gICAgICAgICAgICAgICAgUk9VVEVTLlNJR05fSU5fU09DSUFMX0NBTExCQUNLLFxuICAgICAgICAgICAgICAgIFJPVVRFUy5TSUdOX0lOX09BVVRIX0NBTExCQUNLLFxuICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBoYW5kbGVyOiBjcmVhdGVBdXRoTWlkZGxld2FyZShhc3luYyAocmF3Q3R4KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjdHggPSBuYXJyb3dSZXF1ZXN0Q3R4KHJhd0N0eCk7XG4gICAgICAgICAgICBpZiAoIWN0eCkgcmV0dXJuO1xuICAgICAgICAgICAgY29uc3Qgc2Vzc2lvblVzZXIgPSBjdHguY29udGV4dC5zZXNzaW9uPy51c2VyO1xuICAgICAgICAgICAgY29uc3Qgc2Vzc2lvblVzZXJJZCA9IHNlc3Npb25Vc2VyPy5pZCA/PyBcInVua25vd25cIjtcbiAgICAgICAgICAgIGNvbnN0IHRyaWdnZXIgPSBnZXRUcmlnZ2VySW5mbyhjdHgucGF0aCwgc2Vzc2lvblVzZXJJZCwgc2Vzc2lvblVzZXJJZCk7XG4gICAgICAgICAgICBjb25zdCBsb2NhdGlvbiA9IGxvY2F0aW9uRm9yKGN0eCk7XG4gICAgICAgICAgICBjb25zdCByZXR1cm5lZCA9IGN0eC5jb250ZXh0LnJldHVybmVkO1xuICAgICAgICAgICAgY29uc3QgaXNFcnJvcmVkID0gcmV0dXJuZWQgaW5zdGFuY2VvZiBFcnJvcjtcblxuICAgICAgICAgICAgLy8gdmVyaWZpY2F0aW9uIGVtYWlsIHNlbnRcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgbWF0Y2hlc0FueVJvdXRlKGN0eC5wYXRoLCBbUk9VVEVTLlNFTkRfVkVSSUZJQ0FUSU9OX0VNQUlMXSkgJiZcbiAgICAgICAgICAgICAgY3R4LmNvbnRleHQuc2Vzc2lvbiAmJlxuICAgICAgICAgICAgICAhaXNFcnJvcmVkXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbkVudGl0eSA9IGN0eC5jb250ZXh0LnNlc3Npb24uc2Vzc2lvbiBhcyBTZXNzaW9uU25hcHNob3QgfCB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgIGNvbnN0IHVzZXIgPSBjdHguY29udGV4dC5zZXNzaW9uLnVzZXIgYXNcbiAgICAgICAgICAgICAgICB8IHsgbmFtZT86IHN0cmluZzsgZW1haWw/OiBzdHJpbmcgfVxuICAgICAgICAgICAgICAgIHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgICBpZiAoc2Vzc2lvbkVudGl0eSAmJiB1c2VyKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgZW1pdChcbiAgICAgICAgICAgICAgICAgIGNhdGFsb2cuc2Vzc2lvbi50cmFja0VtYWlsVmVyaWZpY2F0aW9uU2VudChzZXNzaW9uRW50aXR5LCB1c2VyLCB0cmlnZ2VyKSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGJvZHkgPVxuICAgICAgICAgICAgICAoY3R4LmJvZHkgYXMgeyBlbWFpbD86IHN0cmluZzsgcHJvdmlkZXI/OiBzdHJpbmc7IGlkVG9rZW4/OiBzdHJpbmcgfSB8IG51bGwpID8/IG51bGw7XG4gICAgICAgICAgICAvLyBlbWFpbCBzaWduLWluIGF0dGVtcHQgZmFpbGVkXG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIG1hdGNoZXNBbnlSb3V0ZShjdHgucGF0aCwgW1JPVVRFUy5TSUdOX0lOX0VNQUlMLCBST1VURVMuU0lHTl9JTl9FTUFJTF9PVFBdKSAmJlxuICAgICAgICAgICAgICBpc0Vycm9yZWQgJiZcbiAgICAgICAgICAgICAgYm9keT8uZW1haWxcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICBjb25zdCB1c2VyID0gYXdhaXQgZmV0Y2hVc2VyQnkoY3R4LCBcImVtYWlsXCIsIGJvZHkuZW1haWwpO1xuICAgICAgICAgICAgICBhd2FpdCBlbWl0KFxuICAgICAgICAgICAgICAgIGNhdGFsb2cuc2Vzc2lvbi50cmFja0VtYWlsU2lnbkluQXR0ZW1wdChcbiAgICAgICAgICAgICAgICAgIHsgZW1haWw6IGJvZHkuZW1haWwsIGxvZ2luTWV0aG9kOiBnZXRMb2dpbk1ldGhvZChjdHgucGF0aCwgY3R4LnBhcmFtcz8uaWQpIH0sXG4gICAgICAgICAgICAgICAgICB1c2VyLFxuICAgICAgICAgICAgICAgICAgdHJpZ2dlcixcbiAgICAgICAgICAgICAgICAgIGxvY2F0aW9uLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBzb2NpYWwgc2lnbi1pbiBhdHRlbXB0IGZhaWxlZCAoUE9TVClcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgbWF0Y2hlc0FueVJvdXRlKGN0eC5wYXRoLCBbUk9VVEVTLlNJR05fSU5fU09DSUFMXSkgJiZcbiAgICAgICAgICAgICAgaXNFcnJvcmVkICYmXG4gICAgICAgICAgICAgIGJvZHk/LnByb3ZpZGVyICYmXG4gICAgICAgICAgICAgIGJvZHk/LmlkVG9rZW5cbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICBhd2FpdCBlbWl0KFxuICAgICAgICAgICAgICAgIGNhdGFsb2cuc2Vzc2lvbi50cmFja1NvY2lhbFNpZ25JbkF0dGVtcHQoXG4gICAgICAgICAgICAgICAgICB7IGxvZ2luTWV0aG9kOiBnZXRMb2dpbk1ldGhvZChjdHgucGF0aCwgY3R4LnBhcmFtcz8uaWQpIH0sXG4gICAgICAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgICAgICAgdHJpZ2dlcixcbiAgICAgICAgICAgICAgICAgIGxvY2F0aW9uLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBzb2NpYWwgcmVkaXJlY3Rpb24gY2FsbGJhY2sgZmFpbGVkIChHRVQpXG4gICAgICAgICAgICBpZiAobWF0Y2hlc0FueVJvdXRlKGN0eC5wYXRoLCBbUk9VVEVTLlNJR05fSU5fU09DSUFMX0NBTExCQUNLXSkgJiYgaXNFcnJvcmVkKSB7XG4gICAgICAgICAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgICAgICAgICAgY2F0YWxvZy5zZXNzaW9uLnRyYWNrU29jaWFsU2lnbkluUmVkaXJlY3Rpb25BdHRlbXB0KFxuICAgICAgICAgICAgICAgICAgeyBsb2dpbk1ldGhvZDogZ2V0TG9naW5NZXRob2QoY3R4LnBhdGgsIGN0eC5wYXJhbXM/LmlkKSB9LFxuICAgICAgICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgICAgICAgIHRyaWdnZXIsXG4gICAgICAgICAgICAgICAgICBsb2NhdGlvbixcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9LFxuICB9O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBPcmdhbml6YXRpb24gaG9vayDtlanshLEgKG9yZ2FuaXphdGlvbiDtlIzrn6zqt7jsnbjsnbQg7Zmc7ISx7ZmU65CcIOqyveyasOyXkOunjClcbi8vIGRhc2ggNzE5Mi03MjgxIOuvuOufrC5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbnR5cGUgRXZlbnRFbWl0dGVyID0gKGV2ZW50OiBBdWRpdExvZ0V2ZW50KSA9PiBQcm9taXNlPHZvaWQ+O1xudHlwZSBBdWRpdExvZ2dlciA9IFJldHVyblR5cGU8dHlwZW9mIGdldExvZ2dlcj47XG5cbmZ1bmN0aW9uIGluc3RhbGxPcmdhbml6YXRpb25Ib29rcyhcbiAgcGx1Z2luQ3R4OiB1bmtub3duLFxuICBjYXRhbG9nOiBSZXR1cm5UeXBlPHR5cGVvZiBidWlsZEF1ZGl0RXZlbnRDYXRhbG9nPixcbiAgZW1pdDogRXZlbnRFbWl0dGVyLFxuICBsb2dnZXI6IEF1ZGl0TG9nZ2VyLFxuKTogdm9pZCB7XG4gIGNvbnN0IGdldFBsdWdpbiA9IChwbHVnaW5DdHggYXMgeyBnZXRQbHVnaW4/OiAoaWQ6IHN0cmluZykgPT4gdW5rbm93biB9KT8uZ2V0UGx1Z2luO1xuICBjb25zdCBvcmdhbml6YXRpb25QbHVnaW4gPVxuICAgIHR5cGVvZiBnZXRQbHVnaW4gPT09IFwiZnVuY3Rpb25cIiA/IGdldFBsdWdpbi5jYWxsKHBsdWdpbkN0eCwgXCJvcmdhbml6YXRpb25cIikgOiBudWxsO1xuXG4gIGlmICghb3JnYW5pemF0aW9uUGx1Z2luIHx8IHR5cGVvZiBvcmdhbml6YXRpb25QbHVnaW4gIT09IFwib2JqZWN0XCIpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJvcmdhbml6YXRpb24gcGx1Z2luIG5vdCBhY3RpdmU7IHNraXBwaW5nIGluc3RydW1lbnRhdGlvblwiKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBvcmdQbHVnaW4gPSBvcmdhbml6YXRpb25QbHVnaW4gYXMge1xuICAgIG9wdGlvbnM/OiB7IG9yZ2FuaXphdGlvbkhvb2tzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfTtcbiAgfTtcbiAgb3JnUGx1Z2luLm9wdGlvbnMgPSBvcmdQbHVnaW4ub3B0aW9ucyA/PyB7fTtcbiAgY29uc3QgaG9va3MgPSAob3JnUGx1Z2luLm9wdGlvbnMub3JnYW5pemF0aW9uSG9va3MgPSBvcmdQbHVnaW4ub3B0aW9ucy5vcmdhbml6YXRpb25Ib29rcyA/PyB7fSk7XG5cbiAgd3JhcE9yZ0hvb2s8eyBvcmdhbml6YXRpb246IE9yZ2FuaXphdGlvblNuYXBzaG90OyB1c2VyOiBVc2VyU25hcHNob3QgfT4oXG4gICAgaG9va3MsXG4gICAgXCJhZnRlckNyZWF0ZU9yZ2FuaXphdGlvblwiLFxuICAgIGFzeW5jIChwKSA9PlxuICAgICAgZW1pdChcbiAgICAgICAgY2F0YWxvZy5vcmdhbml6YXRpb24udHJhY2tPcmdhbml6YXRpb25DcmVhdGVkKFxuICAgICAgICAgIHAub3JnYW5pemF0aW9uLFxuICAgICAgICAgIGdldE9yZ2FuaXphdGlvblRyaWdnZXJJbmZvKHAudXNlciksXG4gICAgICAgICksXG4gICAgICApLFxuICApO1xuXG4gIHdyYXBPcmdIb29rPHsgb3JnYW5pemF0aW9uPzogT3JnYW5pemF0aW9uU25hcHNob3Q7IHVzZXI6IFVzZXJTbmFwc2hvdCB9PihcbiAgICBob29rcyxcbiAgICBcImFmdGVyVXBkYXRlT3JnYW5pemF0aW9uXCIsXG4gICAgYXN5bmMgKHApID0+IHtcbiAgICAgIGlmICghcC5vcmdhbml6YXRpb24pIHJldHVybjtcbiAgICAgIGF3YWl0IGVtaXQoXG4gICAgICAgIGNhdGFsb2cub3JnYW5pemF0aW9uLnRyYWNrT3JnYW5pemF0aW9uVXBkYXRlZChcbiAgICAgICAgICBwLm9yZ2FuaXphdGlvbixcbiAgICAgICAgICBnZXRPcmdhbml6YXRpb25UcmlnZ2VySW5mbyhwLnVzZXIpLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICB9LFxuICApO1xuXG4gIHdyYXBPcmdIb29rPHtcbiAgICBvcmdhbml6YXRpb246IE9yZ2FuaXphdGlvblNuYXBzaG90O1xuICAgIG1lbWJlcjogTWVtYmVyU25hcHNob3Q7XG4gICAgdXNlcjogVXNlclNuYXBzaG90O1xuICB9Pihob29rcywgXCJhZnRlckFkZE1lbWJlclwiLCBhc3luYyAocCkgPT5cbiAgICBlbWl0KFxuICAgICAgY2F0YWxvZy5tZW1iZXIudHJhY2tPcmdhbml6YXRpb25NZW1iZXJBZGRlZChcbiAgICAgICAgcC5vcmdhbml6YXRpb24sXG4gICAgICAgIHAubWVtYmVyLFxuICAgICAgICBwLnVzZXIsXG4gICAgICAgIGdldE9yZ2FuaXphdGlvblRyaWdnZXJJbmZvKHAudXNlciksXG4gICAgICApLFxuICAgICksXG4gICk7XG5cbiAgd3JhcE9yZ0hvb2s8e1xuICAgIG9yZ2FuaXphdGlvbjogT3JnYW5pemF0aW9uU25hcHNob3Q7XG4gICAgbWVtYmVyOiBNZW1iZXJTbmFwc2hvdDtcbiAgICB1c2VyOiBVc2VyU25hcHNob3Q7XG4gIH0+KGhvb2tzLCBcImFmdGVyUmVtb3ZlTWVtYmVyXCIsIGFzeW5jIChwKSA9PlxuICAgIGVtaXQoXG4gICAgICBjYXRhbG9nLm1lbWJlci50cmFja09yZ2FuaXphdGlvbk1lbWJlclJlbW92ZWQoXG4gICAgICAgIHAub3JnYW5pemF0aW9uLFxuICAgICAgICBwLm1lbWJlcixcbiAgICAgICAgcC51c2VyLFxuICAgICAgICBnZXRPcmdhbml6YXRpb25UcmlnZ2VySW5mbyhwLnVzZXIpLFxuICAgICAgKSxcbiAgICApLFxuICApO1xuXG4gIHdyYXBPcmdIb29rPHtcbiAgICBvcmdhbml6YXRpb246IE9yZ2FuaXphdGlvblNuYXBzaG90O1xuICAgIG1lbWJlcjogTWVtYmVyU25hcHNob3Q7XG4gICAgdXNlcjogVXNlclNuYXBzaG90O1xuICAgIHByZXZpb3VzUm9sZTogc3RyaW5nO1xuICB9Pihob29rcywgXCJhZnRlclVwZGF0ZU1lbWJlclJvbGVcIiwgYXN5bmMgKHApID0+XG4gICAgZW1pdChcbiAgICAgIGNhdGFsb2cubWVtYmVyLnRyYWNrT3JnYW5pemF0aW9uTWVtYmVyUm9sZVVwZGF0ZWQoXG4gICAgICAgIHAub3JnYW5pemF0aW9uLFxuICAgICAgICBwLm1lbWJlcixcbiAgICAgICAgcC51c2VyLFxuICAgICAgICBwLnByZXZpb3VzUm9sZSxcbiAgICAgICAgZ2V0T3JnYW5pemF0aW9uVHJpZ2dlckluZm8ocC51c2VyKSxcbiAgICAgICksXG4gICAgKSxcbiAgKTtcblxuICB3cmFwT3JnSG9vazx7XG4gICAgb3JnYW5pemF0aW9uOiBPcmdhbml6YXRpb25TbmFwc2hvdDtcbiAgICBpbnZpdGF0aW9uOiBJbnZpdGF0aW9uU25hcHNob3Q7XG4gICAgaW52aXRlcjogVXNlclNuYXBzaG90O1xuICB9Pihob29rcywgXCJhZnRlckNyZWF0ZUludml0YXRpb25cIiwgYXN5bmMgKHApID0+XG4gICAgZW1pdChcbiAgICAgIGNhdGFsb2cuaW52aXRhdGlvbi50cmFja09yZ2FuaXphdGlvbk1lbWJlckludml0ZWQoXG4gICAgICAgIHAub3JnYW5pemF0aW9uLFxuICAgICAgICBwLmludml0YXRpb24sXG4gICAgICAgIHAuaW52aXRlcixcbiAgICAgICAgZ2V0T3JnYW5pemF0aW9uVHJpZ2dlckluZm8ocC5pbnZpdGVyKSxcbiAgICAgICksXG4gICAgKSxcbiAgKTtcblxuICB3cmFwT3JnSG9vazx7XG4gICAgb3JnYW5pemF0aW9uOiBPcmdhbml6YXRpb25TbmFwc2hvdDtcbiAgICBpbnZpdGF0aW9uOiBJbnZpdGF0aW9uU25hcHNob3Q7XG4gICAgbWVtYmVyOiBNZW1iZXJTbmFwc2hvdDtcbiAgICB1c2VyOiBVc2VyU25hcHNob3Q7XG4gIH0+KGhvb2tzLCBcImFmdGVyQWNjZXB0SW52aXRhdGlvblwiLCBhc3luYyAocCkgPT5cbiAgICBlbWl0KFxuICAgICAgY2F0YWxvZy5pbnZpdGF0aW9uLnRyYWNrT3JnYW5pemF0aW9uTWVtYmVySW52aXRlQWNjZXB0ZWQoXG4gICAgICAgIHAub3JnYW5pemF0aW9uLFxuICAgICAgICBwLmludml0YXRpb24sXG4gICAgICAgIHAubWVtYmVyLFxuICAgICAgICBwLnVzZXIsXG4gICAgICAgIGdldE9yZ2FuaXphdGlvblRyaWdnZXJJbmZvKHAudXNlciksXG4gICAgICApLFxuICAgICksXG4gICk7XG5cbiAgd3JhcE9yZ0hvb2s8e1xuICAgIG9yZ2FuaXphdGlvbjogT3JnYW5pemF0aW9uU25hcHNob3Q7XG4gICAgaW52aXRhdGlvbjogSW52aXRhdGlvblNuYXBzaG90O1xuICAgIHVzZXI6IFVzZXJTbmFwc2hvdDtcbiAgfT4oaG9va3MsIFwiYWZ0ZXJSZWplY3RJbnZpdGF0aW9uXCIsIGFzeW5jIChwKSA9PlxuICAgIGVtaXQoXG4gICAgICBjYXRhbG9nLmludml0YXRpb24udHJhY2tPcmdhbml6YXRpb25NZW1iZXJJbnZpdGVSZWplY3RlZChcbiAgICAgICAgcC5vcmdhbml6YXRpb24sXG4gICAgICAgIHAuaW52aXRhdGlvbixcbiAgICAgICAgcC51c2VyLFxuICAgICAgICBnZXRPcmdhbml6YXRpb25UcmlnZ2VySW5mbyhwLnVzZXIpLFxuICAgICAgKSxcbiAgICApLFxuICApO1xuXG4gIHdyYXBPcmdIb29rPHtcbiAgICBvcmdhbml6YXRpb246IE9yZ2FuaXphdGlvblNuYXBzaG90O1xuICAgIGludml0YXRpb246IEludml0YXRpb25TbmFwc2hvdDtcbiAgICBjYW5jZWxsZWRCeTogVXNlclNuYXBzaG90O1xuICB9Pihob29rcywgXCJhZnRlckNhbmNlbEludml0YXRpb25cIiwgYXN5bmMgKHApID0+XG4gICAgZW1pdChcbiAgICAgIGNhdGFsb2cuaW52aXRhdGlvbi50cmFja09yZ2FuaXphdGlvbk1lbWJlckludml0ZUNhbmNlbGVkKFxuICAgICAgICBwLm9yZ2FuaXphdGlvbixcbiAgICAgICAgcC5pbnZpdGF0aW9uLFxuICAgICAgICBwLmNhbmNlbGxlZEJ5LFxuICAgICAgICBnZXRPcmdhbml6YXRpb25UcmlnZ2VySW5mbyhwLmNhbmNlbGxlZEJ5KSxcbiAgICAgICksXG4gICAgKSxcbiAgKTtcblxuICB3cmFwT3JnSG9vazx7XG4gICAgb3JnYW5pemF0aW9uOiBPcmdhbml6YXRpb25TbmFwc2hvdDtcbiAgICB0ZWFtOiBUZWFtU25hcHNob3Q7XG4gICAgdXNlcjogVXNlclNuYXBzaG90O1xuICB9Pihob29rcywgXCJhZnRlckNyZWF0ZVRlYW1cIiwgYXN5bmMgKHApID0+XG4gICAgZW1pdChcbiAgICAgIGNhdGFsb2cudGVhbS50cmFja09yZ2FuaXphdGlvblRlYW1DcmVhdGVkKFxuICAgICAgICBwLm9yZ2FuaXphdGlvbixcbiAgICAgICAgcC50ZWFtLFxuICAgICAgICBnZXRPcmdhbml6YXRpb25UcmlnZ2VySW5mbyhwLnVzZXIpLFxuICAgICAgKSxcbiAgICApLFxuICApO1xuXG4gIHdyYXBPcmdIb29rPHtcbiAgICBvcmdhbml6YXRpb246IE9yZ2FuaXphdGlvblNuYXBzaG90O1xuICAgIHRlYW0/OiBUZWFtU25hcHNob3Q7XG4gICAgdXNlcjogVXNlclNuYXBzaG90O1xuICB9Pihob29rcywgXCJhZnRlclVwZGF0ZVRlYW1cIiwgYXN5bmMgKHApID0+IHtcbiAgICBpZiAoIXAudGVhbSkgcmV0dXJuO1xuICAgIGF3YWl0IGVtaXQoXG4gICAgICBjYXRhbG9nLnRlYW0udHJhY2tPcmdhbml6YXRpb25UZWFtVXBkYXRlZChcbiAgICAgICAgcC5vcmdhbml6YXRpb24sXG4gICAgICAgIHAudGVhbSxcbiAgICAgICAgZ2V0T3JnYW5pemF0aW9uVHJpZ2dlckluZm8ocC51c2VyKSxcbiAgICAgICksXG4gICAgKTtcbiAgfSk7XG5cbiAgd3JhcE9yZ0hvb2s8e1xuICAgIG9yZ2FuaXphdGlvbjogT3JnYW5pemF0aW9uU25hcHNob3Q7XG4gICAgdGVhbTogVGVhbVNuYXBzaG90O1xuICAgIHVzZXI6IFVzZXJTbmFwc2hvdDtcbiAgfT4oaG9va3MsIFwiYWZ0ZXJEZWxldGVUZWFtXCIsIGFzeW5jIChwKSA9PlxuICAgIGVtaXQoXG4gICAgICBjYXRhbG9nLnRlYW0udHJhY2tPcmdhbml6YXRpb25UZWFtRGVsZXRlZChcbiAgICAgICAgcC5vcmdhbml6YXRpb24sXG4gICAgICAgIHAudGVhbSxcbiAgICAgICAgZ2V0T3JnYW5pemF0aW9uVHJpZ2dlckluZm8ocC51c2VyKSxcbiAgICAgICksXG4gICAgKSxcbiAgKTtcblxuICB3cmFwT3JnSG9vazx7XG4gICAgb3JnYW5pemF0aW9uOiBPcmdhbml6YXRpb25TbmFwc2hvdDtcbiAgICB0ZWFtOiBUZWFtU25hcHNob3Q7XG4gICAgdXNlcjogVXNlclNuYXBzaG90O1xuICAgIHRlYW1NZW1iZXI6IHsgdGVhbUlkOiBzdHJpbmc7IHVzZXJJZDogc3RyaW5nIH07XG4gIH0+KGhvb2tzLCBcImFmdGVyQWRkVGVhbU1lbWJlclwiLCBhc3luYyAocCkgPT5cbiAgICBlbWl0KFxuICAgICAgY2F0YWxvZy50ZWFtLnRyYWNrT3JnYW5pemF0aW9uVGVhbU1lbWJlckFkZGVkKFxuICAgICAgICBwLm9yZ2FuaXphdGlvbixcbiAgICAgICAgcC50ZWFtLFxuICAgICAgICBwLnVzZXIsXG4gICAgICAgIHAudGVhbU1lbWJlcixcbiAgICAgICAgZ2V0T3JnYW5pemF0aW9uVHJpZ2dlckluZm8ocC51c2VyKSxcbiAgICAgICksXG4gICAgKSxcbiAgKTtcblxuICB3cmFwT3JnSG9vazx7XG4gICAgb3JnYW5pemF0aW9uOiBPcmdhbml6YXRpb25TbmFwc2hvdDtcbiAgICB0ZWFtOiBUZWFtU25hcHNob3Q7XG4gICAgdXNlcjogVXNlclNuYXBzaG90O1xuICAgIHRlYW1NZW1iZXI6IHsgdGVhbUlkOiBzdHJpbmc7IHVzZXJJZDogc3RyaW5nIH07XG4gIH0+KGhvb2tzLCBcImFmdGVyUmVtb3ZlVGVhbU1lbWJlclwiLCBhc3luYyAocCkgPT5cbiAgICBlbWl0KFxuICAgICAgY2F0YWxvZy50ZWFtLnRyYWNrT3JnYW5pemF0aW9uVGVhbU1lbWJlclJlbW92ZWQoXG4gICAgICAgIHAub3JnYW5pemF0aW9uLFxuICAgICAgICBwLnRlYW0sXG4gICAgICAgIHAudXNlcixcbiAgICAgICAgcC50ZWFtTWVtYmVyLFxuICAgICAgICBnZXRPcmdhbml6YXRpb25UcmlnZ2VySW5mbyhwLnVzZXIpLFxuICAgICAgKSxcbiAgICApLFxuICApO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztTQUl1QztBQXNCdkMsTUFBTSxjQUFjLFVBQTBCLE1BQU0sTUFBTSxJQUFJLENBQUMsTUFBTTtBQUNyRSxNQUFNLGVBQWUsVUFBMEIsTUFBTSxRQUFRLHVCQUF1QixPQUFPO0FBQzNGLE1BQU0sZ0JBQWdCLFVBQTBCO0NBQzlDLE1BQU0sVUFBVSxZQUFZLFdBQVcsTUFBTSxDQUFDLENBQUMsUUFBUSxlQUFlLFNBQVM7QUFDL0UsUUFBTyxJQUFJLE9BQU8sR0FBRyxRQUFRLFlBQVk7O0FBRTNDLE1BQU0sbUJBQW1CLFdBQStCLFdBQXVDO0FBQzdGLEtBQUksQ0FBQyxVQUFXLFFBQU87Q0FDdkIsTUFBTSxZQUFZLFdBQVcsVUFBVTtBQUN2QyxRQUFPLE9BQU8s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
@@ -1,9 +1,9 @@
1
1
  import { type Knex } from "knex";
2
- import { type AuditLogEvent } from "./audit-log-proxy-types";
2
+ import { type AuditLogEvent } from "./audit-log/events";
3
3
  /**
4
- * Better Auth dash() 이벤트를 audit_events 테이블에 적재합니다.
4
+ * sonamuAuditLog 플러그인이 구성한 AuditLogEvent를 audit_events 테이블에 적재합니다.
5
5
  * ON CONFLICT (dedupe_key) DO NOTHING으로 중복을 silent 무시합니다.
6
- * auth.auditLog: true 설정 시 sonamu 내부에서 자동으로 호출됩니다.
6
+ * auth.plugins에 sonamuAuditLog() 추가 시 sonamu 내부에서 자동으로 호출됩니다.
7
7
  */
8
8
  export declare function ingestAuditEvent(db: Knex, event: AuditLogEvent): Promise<void>;
9
9
  //# sourceMappingURL=audit-log-ingestor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit-log-ingestor.d.ts","sourceRoot":"","sources":["../../src/auth/audit-log-ingestor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAwI7D;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAwFpF"}
1
+ {"version":3,"file":"audit-log-ingestor.d.ts","sourceRoot":"","sources":["../../src/auth/audit-log-ingestor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAuIxD;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAwFpF"}