@dbx-tools/appkit 0.9.184 → 0.9.187

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -142,6 +142,7 @@ reason.
142
142
  | Option | Type | Default | Description |
143
143
  | --------------- | ------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
144
144
  | `autoConfigure` | `"provision" \| "env" \| false` | `"provision"` | What to run before AppKit boots. `"provision"` resolves the Lakebase connection into `process.env` and grants the AppKit cache schema. `"env"` resolves the connection only. `false` skips auto-configuration. Omit it to gate resolution on native `lakebase` or `database`. Implicit database-only resolution does not grant the cache schema. |
145
+ | `debug` | `"auto" \| boolean` | `"auto"` | Registers the browser debug-capture plugin. Auto mode enables it only when `NODE_ENV=development`; `true` and `false` force the choice. |
145
146
  | `interceptor` | `Interceptor \| Interceptor[]` | none | One or many callbacks handed an `InterceptorContext` after auto-config computes the env and before AppKit boots. The context carries the resolved env and AppKit lifecycle registration through `onLifecycle`. |
146
147
 
147
148
  Set `autoConfigure` explicitly on an app that registers no `lakebase()` plugin but
@@ -167,6 +168,23 @@ AppKit closes injected storage during shutdown. Native composition should call
167
168
  `close()` when it owns the storage directly. That drains tracked write-behind
168
169
  work before disconnecting the persistent levels.
169
170
 
171
+ ## Browser debug capture
172
+
173
+ Development `createApp()` calls automatically register a hidden browser capture
174
+ route. `@dbx-tools/ui/react` exposes `BrowserDebugCaptureButton`, which records
175
+ bounded browser, viewport, focus, input, pointer, touch, scroll, and resize
176
+ diagnostics without recording input values or printable key content. Captures
177
+ are JSONL files under `.tmp/debug-captures` in development.
178
+
179
+ Register the plugin explicitly when native AppKit composition or a custom
180
+ capture directory is required:
181
+
182
+ ```ts
183
+ import { debugCapture } from "@dbx-tools/appkit/debug";
184
+
185
+ debugCapture({ directory: ".tmp/browser-captures" });
186
+ ```
187
+
170
188
  ## Filesystem cache plugin
171
189
 
172
190
  Register `filesCache()` when provider-backed filesystems should share one
package/index.debug.ts ADDED
@@ -0,0 +1,9 @@
1
+ // GENERATED by projen watch - DO NOT EDIT.
2
+ // Regenerated from the exporting modules in ./src.
3
+ // Hand edits are overwritten on the next watch; this file is read-only.
4
+
5
+ export * as plugin from "./src/debug/plugin.ts";
6
+ export * as storage from "./src/debug/storage.ts";
7
+ export { DebugCapturePlugin, debugCapture } from "./src/debug/plugin.ts";
8
+ export type { DebugCapturePluginConfig, DebugCapturePluginExports } from "./src/debug/plugin.ts";
9
+ export { defaultDebugCaptureDirectory, DebugCaptureStorage } from "./src/debug/storage.ts";
package/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
 
5
5
  export const PACKAGE_IDENTIFIER = "@dbx-tools/appkit";
6
- export const PACKAGE_VERSION = "0.9.184";
6
+ export const PACKAGE_VERSION = "0.9.187";
7
7
  export * as appkit from "./src/appkit.ts";
8
8
  export * as brandContext from "./src/brand-context.ts";
9
9
  export * as cacheStorage from "./src/cache-storage.ts";
@@ -21,8 +21,8 @@ export * as telemetry from "./src/telemetry.ts";
21
21
  export * as toolOperations from "./src/tool-operations.ts";
22
22
  export * as toolProvider from "./src/tool-provider.ts";
23
23
  export * as toolkitEntries from "./src/toolkit-entries.ts";
24
- export { autoConfigure, createApp, tryGetExecutionContext, ensureInitialized } from "./src/appkit.ts";
25
- export type { AutoConfigureMode, CreateAppConfig, ExecutionContextLike, WorkspaceClientLike } from "./src/appkit.ts";
24
+ export { debugCaptureEnabled, autoConfigure, createApp, tryGetExecutionContext, ensureInitialized } from "./src/appkit.ts";
25
+ export type { AutoConfigureMode, DebugCaptureMode, CreateAppConfig, ExecutionContextLike, WorkspaceClientLike } from "./src/appkit.ts";
26
26
  export { loadBrandContext, getBrandContext } from "./src/brand-context.ts";
27
27
  export { AppKitCacheStorage, loadPersistentStorage, softenInitialize, probeStorage, createAppKitCacheStorage } from "./src/cache-storage.ts";
28
28
  export type { AppKitCacheStorageOptions, PersistentStorageBase } from "./src/cache-storage.ts";
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export declare const PACKAGE_IDENTIFIER = "@dbx-tools/appkit";
2
- export declare const PACKAGE_VERSION = "0.9.184";
2
+ export declare const PACKAGE_VERSION = "0.9.187";
3
3
  export * as appkit from "./src/appkit.ts";
4
4
  export * as brandContext from "./src/brand-context.ts";
5
5
  export * as cacheStorage from "./src/cache-storage.ts";
@@ -17,8 +17,8 @@ export * as telemetry from "./src/telemetry.ts";
17
17
  export * as toolOperations from "./src/tool-operations.ts";
18
18
  export * as toolProvider from "./src/tool-provider.ts";
19
19
  export * as toolkitEntries from "./src/toolkit-entries.ts";
20
- export { autoConfigure, createApp, tryGetExecutionContext, ensureInitialized } from "./src/appkit.ts";
21
- export type { AutoConfigureMode, CreateAppConfig, ExecutionContextLike, WorkspaceClientLike } from "./src/appkit.ts";
20
+ export { debugCaptureEnabled, autoConfigure, createApp, tryGetExecutionContext, ensureInitialized } from "./src/appkit.ts";
21
+ export type { AutoConfigureMode, DebugCaptureMode, CreateAppConfig, ExecutionContextLike, WorkspaceClientLike } from "./src/appkit.ts";
22
22
  export { loadBrandContext, getBrandContext } from "./src/brand-context.ts";
23
23
  export { AppKitCacheStorage, loadPersistentStorage, softenInitialize, probeStorage, createAppKitCacheStorage } from "./src/cache-storage.ts";
24
24
  export type { AppKitCacheStorageOptions, PersistentStorageBase } from "./src/cache-storage.ts";
@@ -0,0 +1,5 @@
1
+ export * as plugin from "./src/debug/plugin.ts";
2
+ export * as storage from "./src/debug/storage.ts";
3
+ export { DebugCapturePlugin, debugCapture } from "./src/debug/plugin.ts";
4
+ export type { DebugCapturePluginConfig, DebugCapturePluginExports } from "./src/debug/plugin.ts";
5
+ export { defaultDebugCaptureDirectory, DebugCaptureStorage } from "./src/debug/storage.ts";
@@ -0,0 +1,8 @@
1
+ // GENERATED by projen watch - DO NOT EDIT.
2
+ // Regenerated from the exporting modules in ./src.
3
+ // Hand edits are overwritten on the next watch; this file is read-only.
4
+ export * as plugin from "./src/debug/plugin.js";
5
+ export * as storage from "./src/debug/storage.js";
6
+ export { DebugCapturePlugin, debugCapture } from "./src/debug/plugin.js";
7
+ export { defaultDebugCaptureDirectory, DebugCaptureStorage } from "./src/debug/storage.js";
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZGVidWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC5kZWJ1Zy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssTUFBTSxNQUFNLHVCQUF1QixDQUFDO0FBQ2hELE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFDbEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFlBQVksRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRXpFLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHdCQUF3QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gR0VORVJBVEVEIGJ5IHByb2plbiB3YXRjaCAtIERPIE5PVCBFRElULlxuLy8gUmVnZW5lcmF0ZWQgZnJvbSB0aGUgZXhwb3J0aW5nIG1vZHVsZXMgaW4gLi9zcmMuXG4vLyBIYW5kIGVkaXRzIGFyZSBvdmVyd3JpdHRlbiBvbiB0aGUgbmV4dCB3YXRjaDsgdGhpcyBmaWxlIGlzIHJlYWQtb25seS5cblxuZXhwb3J0ICogYXMgcGx1Z2luIGZyb20gXCIuL3NyYy9kZWJ1Zy9wbHVnaW4udHNcIjtcbmV4cG9ydCAqIGFzIHN0b3JhZ2UgZnJvbSBcIi4vc3JjL2RlYnVnL3N0b3JhZ2UudHNcIjtcbmV4cG9ydCB7IERlYnVnQ2FwdHVyZVBsdWdpbiwgZGVidWdDYXB0dXJlIH0gZnJvbSBcIi4vc3JjL2RlYnVnL3BsdWdpbi50c1wiO1xuZXhwb3J0IHR5cGUgeyBEZWJ1Z0NhcHR1cmVQbHVnaW5Db25maWcsIERlYnVnQ2FwdHVyZVBsdWdpbkV4cG9ydHMgfSBmcm9tIFwiLi9zcmMvZGVidWcvcGx1Z2luLnRzXCI7XG5leHBvcnQgeyBkZWZhdWx0RGVidWdDYXB0dXJlRGlyZWN0b3J5LCBEZWJ1Z0NhcHR1cmVTdG9yYWdlIH0gZnJvbSBcIi4vc3JjL2RlYnVnL3N0b3JhZ2UudHNcIjtcbiJdfQ==
package/lib/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // Regenerated from the exporting modules in ./src.
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
  export const PACKAGE_IDENTIFIER = "@dbx-tools/appkit";
5
- export const PACKAGE_VERSION = "0.9.184";
5
+ export const PACKAGE_VERSION = "0.9.187";
6
6
  export * as appkit from "./src/appkit.js";
7
7
  export * as brandContext from "./src/brand-context.js";
8
8
  export * as cacheStorage from "./src/cache-storage.js";
@@ -20,7 +20,7 @@ export * as telemetry from "./src/telemetry.js";
20
20
  export * as toolOperations from "./src/tool-operations.js";
21
21
  export * as toolProvider from "./src/tool-provider.js";
22
22
  export * as toolkitEntries from "./src/toolkit-entries.js";
23
- export { autoConfigure, createApp, tryGetExecutionContext, ensureInitialized } from "./src/appkit.js";
23
+ export { debugCaptureEnabled, autoConfigure, createApp, tryGetExecutionContext, ensureInitialized } from "./src/appkit.js";
24
24
  export { loadBrandContext, getBrandContext } from "./src/brand-context.js";
25
25
  export { AppKitCacheStorage, loadPersistentStorage, softenInitialize, probeStorage, createAppKitCacheStorage } from "./src/cache-storage.js";
26
26
  export { toContext } from "./src/databricks.js";
@@ -38,4 +38,4 @@ export { USER_TRACE_ATTRIBUTE, excludeHttpTelemetryRequest, excludeUnparentedOut
38
38
  export { defineOperations, toolRegistryFromOperations } from "./src/tool-operations.js";
39
39
  export { ToolRegistryPlugin } from "./src/tool-provider.js";
40
40
  export { name, entries } from "./src/toolkit-entries.js";
41
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxtQkFBbUIsQ0FBQztBQUN0RCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFlBQVksTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEtBQUssWUFBWSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxVQUFVLE1BQU0scUJBQXFCLENBQUM7QUFDbEQsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEtBQUssV0FBVyxNQUFNLHNCQUFzQixDQUFDO0FBQ3BELE9BQU8sS0FBSyxnQkFBZ0IsTUFBTSw0QkFBNEIsQ0FBQztBQUMvRCxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxXQUFXLE1BQU0sdUJBQXVCLENBQUM7QUFDckQsT0FBTyxLQUFLLGVBQWUsTUFBTSwyQkFBMkIsQ0FBQztBQUM3RCxPQUFPLEtBQUssY0FBYyxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsT0FBTyxLQUFLLFdBQVcsTUFBTSx1QkFBdUIsQ0FBQztBQUNyRCxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxjQUFjLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxLQUFLLFlBQVksTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEtBQUssY0FBYyxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sRUFBRSxhQUFhLEVBQUUsU0FBUyxFQUFFLHNCQUFzQixFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFdEcsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzNFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxxQkFBcUIsRUFBRSxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU3SSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFaEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXZGLE9BQU8sRUFBRSxjQUFjLEVBQUUscUJBQXFCLEVBQUUsbUJBQW1CLEVBQUUsa0JBQWtCLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFFLG1CQUFtQixFQUFFLDZCQUE2QixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFeE0sT0FBTyxFQUFFLHdCQUF3QixFQUFFLHFCQUFxQixFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXhHLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsa0JBQWtCLEVBQUUseUJBQXlCLEVBQUUsa0JBQWtCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVqTixPQUFPLEVBQUUseUJBQXlCLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUU5RixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFckQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFL0QsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFbkUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLG9CQUFvQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDaEYsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTVGLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSwyQkFBMkIsRUFBRSxzQ0FBc0MsRUFBRSxrQkFBa0IsRUFBRSw0QkFBNEIsRUFBRSwyQkFBMkIsRUFBRSwyQkFBMkIsRUFBRSw0QkFBNEIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRXpRLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSwwQkFBMEIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRXhGLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRTVELE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sMEJBQTBCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBHRU5FUkFURUQgYnkgcHJvamVuIHdhdGNoIC0gRE8gTk9UIEVESVQuXG4vLyBSZWdlbmVyYXRlZCBmcm9tIHRoZSBleHBvcnRpbmcgbW9kdWxlcyBpbiAuL3NyYy5cbi8vIEhhbmQgZWRpdHMgYXJlIG92ZXJ3cml0dGVuIG9uIHRoZSBuZXh0IHdhdGNoOyB0aGlzIGZpbGUgaXMgcmVhZC1vbmx5LlxuXG5leHBvcnQgY29uc3QgUEFDS0FHRV9JREVOVElGSUVSID0gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9IFwiMC45LjE4NFwiO1xuZXhwb3J0ICogYXMgYXBwa2l0IGZyb20gXCIuL3NyYy9hcHBraXQudHNcIjtcbmV4cG9ydCAqIGFzIGJyYW5kQ29udGV4dCBmcm9tIFwiLi9zcmMvYnJhbmQtY29udGV4dC50c1wiO1xuZXhwb3J0ICogYXMgY2FjaGVTdG9yYWdlIGZyb20gXCIuL3NyYy9jYWNoZS1zdG9yYWdlLnRzXCI7XG5leHBvcnQgKiBhcyBkYXRhYnJpY2tzIGZyb20gXCIuL3NyYy9kYXRhYnJpY2tzLnRzXCI7XG5leHBvcnQgKiBhcyBpZGVudGl0eSBmcm9tIFwiLi9zcmMvaWRlbnRpdHkudHNcIjtcbmV4cG9ydCAqIGFzIGludGVyY2VwdG9yIGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0ICogYXMgbGFrZWJhc2VSZXNvbHZlciBmcm9tIFwiLi9zcmMvbGFrZWJhc2UtcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCAqIGFzIG1pZ3JhdGlvbiBmcm9tIFwiLi9zcmMvbWlncmF0aW9uLnRzXCI7XG5leHBvcnQgKiBhcyBvcGVuYXBpVG9vbCBmcm9tIFwiLi9zcmMvb3BlbmFwaS10b29sLnRzXCI7XG5leHBvcnQgKiBhcyBwbHVnaW5FeGVjdXRpb24gZnJvbSBcIi4vc3JjL3BsdWdpbi1leGVjdXRpb24udHNcIjtcbmV4cG9ydCAqIGFzIHBsdWdpblJlZ2lzdHJ5IGZyb20gXCIuL3NyYy9wbHVnaW4tcmVnaXN0cnkudHNcIjtcbmV4cG9ydCAqIGFzIHByb3Zpc2lvbiBmcm9tIFwiLi9zcmMvcHJvdmlzaW9uLnRzXCI7XG5leHBvcnQgKiBhcyByZXF1ZXN0VGFncyBmcm9tIFwiLi9zcmMvcmVxdWVzdC10YWdzLnRzXCI7XG5leHBvcnQgKiBhcyB0ZWxlbWV0cnkgZnJvbSBcIi4vc3JjL3RlbGVtZXRyeS50c1wiO1xuZXhwb3J0ICogYXMgdG9vbE9wZXJhdGlvbnMgZnJvbSBcIi4vc3JjL3Rvb2wtb3BlcmF0aW9ucy50c1wiO1xuZXhwb3J0ICogYXMgdG9vbFByb3ZpZGVyIGZyb20gXCIuL3NyYy90b29sLXByb3ZpZGVyLnRzXCI7XG5leHBvcnQgKiBhcyB0b29sa2l0RW50cmllcyBmcm9tIFwiLi9zcmMvdG9vbGtpdC1lbnRyaWVzLnRzXCI7XG5leHBvcnQgeyBhdXRvQ29uZmlndXJlLCBjcmVhdGVBcHAsIHRyeUdldEV4ZWN1dGlvbkNvbnRleHQsIGVuc3VyZUluaXRpYWxpemVkIH0gZnJvbSBcIi4vc3JjL2FwcGtpdC50c1wiO1xuZXhwb3J0IHR5cGUgeyBBdXRvQ29uZmlndXJlTW9kZSwgQ3JlYXRlQXBwQ29uZmlnLCBFeGVjdXRpb25Db250ZXh0TGlrZSwgV29ya3NwYWNlQ2xpZW50TGlrZSB9IGZyb20gXCIuL3NyYy9hcHBraXQudHNcIjtcbmV4cG9ydCB7IGxvYWRCcmFuZENvbnRleHQsIGdldEJyYW5kQ29udGV4dCB9IGZyb20gXCIuL3NyYy9icmFuZC1jb250ZXh0LnRzXCI7XG5leHBvcnQgeyBBcHBLaXRDYWNoZVN0b3JhZ2UsIGxvYWRQZXJzaXN0ZW50U3RvcmFnZSwgc29mdGVuSW5pdGlhbGl6ZSwgcHJvYmVTdG9yYWdlLCBjcmVhdGVBcHBLaXRDYWNoZVN0b3JhZ2UgfSBmcm9tIFwiLi9zcmMvY2FjaGUtc3RvcmFnZS50c1wiO1xuZXhwb3J0IHR5cGUgeyBBcHBLaXRDYWNoZVN0b3JhZ2VPcHRpb25zLCBQZXJzaXN0ZW50U3RvcmFnZUJhc2UgfSBmcm9tIFwiLi9zcmMvY2FjaGUtc3RvcmFnZS50c1wiO1xuZXhwb3J0IHsgdG9Db250ZXh0IH0gZnJvbSBcIi4vc3JjL2RhdGFicmlja3MudHNcIjtcbmV4cG9ydCB0eXBlIHsgQ29udGV4dExpa2UgfSBmcm9tIFwiLi9zcmMvZGF0YWJyaWNrcy50c1wiO1xuZXhwb3J0IHsgRmlsZXNDYWNoZU1hbmFnZXIsIEZpbGVzQ2FjaGVQbHVnaW4sIGZpbGVzQ2FjaGUgfSBmcm9tIFwiLi9zcmMvZmlsZXMtY2FjaGUudHNcIjtcbmV4cG9ydCB0eXBlIHsgRmlsZXNDYWNoZVBsdWdpbkNvbmZpZywgRmlsZXNDYWNoZVNjb3BlLCBGaWxlc0NhY2hlU291cmNlSWRlbnRpdHksIEZpbGVzQ2FjaGVFeHBvcnRzIH0gZnJvbSBcIi4vc3JjL2ZpbGVzLWNhY2hlLnRzXCI7XG5leHBvcnQgeyBJREVOVElUWV9NT0RFUywgREVGQVVMVF9JREVOVElUWV9NT0RFLCByZXNvbHZlSWRlbnRpdHlNb2RlLCByZXF1ZXN0QWNjZXNzVG9rZW4sIHJlcXVlc3RVc2VySWQsIHJlcXVlc3RVc2VyRW1haWwsIHVzZVNlcnZpY2VQcmluY2lwYWwsIGluc3RhbGxBc1VzZXJEZXZlbG9wbWVudFBhdGNoIH0gZnJvbSBcIi4vc3JjL2lkZW50aXR5LnRzXCI7XG5leHBvcnQgdHlwZSB7IElkZW50aXR5TW9kZSwgSGVhZGVyQmVhcmluZyB9IGZyb20gXCIuL3NyYy9pZGVudGl0eS50c1wiO1xuZXhwb3J0IHsgY3JlYXRlSW50ZXJjZXB0b3JDb250ZXh0LCBMaWZlY3ljbGVCcmlkZ2VQbHVnaW4sIGxpZmVjeWNsZUJyaWRnZSB9IGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0IHR5cGUgeyBMaWZlY3ljbGVFdmVudCwgTGlmZWN5Y2xlSGFuZGxlciwgUmVzb2x2ZWRBcHBFbnYsIEludGVyY2VwdG9yQ29udGV4dCwgSW50ZXJjZXB0b3IsIEludGVyY2VwdG9yUnVudGltZSB9IGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0IHsgY2FwdHVyZVNlcnZpY2VQcmluY2lwYWxQb29sLCBwYXJzZVBvcnQsIHBhcnNlU3NsTW9kZSwgbmV4dFBvbGxEZWxheSwgcG9sbERlbGF5LCByZWFkTGFrZWJhc2VJbnB1dHMsIHJlc29sdmVMYWtlYmFzZUNvbm5lY3Rpb24sIGFwcGx5TGFrZWJhc2VUb0VudiwgYXBwbHlMYWtlYmFzZUVudiB9IGZyb20gXCIuL3NyYy9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuZXhwb3J0IHR5cGUgeyBMYWtlYmFzZVJlc29sdmVySW5wdXRzLCBMYWtlYmFzZUNvbm5lY3Rpb24gfSBmcm9tIFwiLi9zcmMvbGFrZWJhc2UtcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCB7IGlzT3duZXJzaGlwTWlncmF0aW9uRXJyb3IsIGhhbmRsZU93bmVyc2hpcE1pZ3JhdGlvbkVycm9yIH0gZnJvbSBcIi4vc3JjL21pZ3JhdGlvbi50c1wiO1xuZXhwb3J0IHR5cGUgeyBPd25lcnNoaXBNaWdyYXRpb25FcnJvck9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvbWlncmF0aW9uLnRzXCI7XG5leHBvcnQgeyBvcGVuQXBpVG9vbHMgfSBmcm9tIFwiLi9zcmMvb3BlbmFwaS10b29sLnRzXCI7XG5leHBvcnQgdHlwZSB7IE9wZW5BcGlIdHRwTWV0aG9kLCBPcGVuQXBpVG9vbCwgT3BlbkFwaVRvb2xzT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9vcGVuYXBpLXRvb2wudHNcIjtcbmV4cG9ydCB7IHJ1blBsdWdpbkV4ZWN1dGlvbiB9IGZyb20gXCIuL3NyYy9wbHVnaW4tZXhlY3V0aW9uLnRzXCI7XG5leHBvcnQgdHlwZSB7IFJ1blBsdWdpbkV4ZWN1dGlvbk9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvcGx1Z2luLWV4ZWN1dGlvbi50c1wiO1xuZXhwb3J0IHsgZGF0YSwgaW5zdGFuY2UsIHJlcXVpcmUgfSBmcm9tIFwiLi9zcmMvcGx1Z2luLXJlZ2lzdHJ5LnRzXCI7XG5leHBvcnQgdHlwZSB7IFBsdWdpbkNvbnRleHRMaWtlIH0gZnJvbSBcIi4vc3JjL3BsdWdpbi1yZWdpc3RyeS50c1wiO1xuZXhwb3J0IHsgY2FjaGVHcmFudFN0YXRlbWVudHMsIHByb3Zpc2lvbkNhY2hlU2NoZW1hIH0gZnJvbSBcIi4vc3JjL3Byb3Zpc2lvbi50c1wiO1xuZXhwb3J0IHsgaW5qZWN0UmVxdWVzdFRhZywgaW5qZWN0UmVxdWVzdFRhZ3MsIGdldFJlcXVlc3RUYWdzIH0gZnJvbSBcIi4vc3JjL3JlcXVlc3QtdGFncy50c1wiO1xuZXhwb3J0IHR5cGUgeyBSZXF1ZXN0VGFnVmFsdWUgfSBmcm9tIFwiLi9zcmMvcmVxdWVzdC10YWdzLnRzXCI7XG5leHBvcnQgeyBVU0VSX1RSQUNFX0FUVFJJQlVURSwgZXhjbHVkZUh0dHBUZWxlbWV0cnlSZXF1ZXN0LCBleGNsdWRlVW5wYXJlbnRlZE91dGdvaW5nSHR0cFRlbGVtZXRyeSwgc3RhbXBIdHRwVHJhY2VVc2VyLCBjb25maWd1cmVOYXRpdmVIdHRwVGVsZW1ldHJ5LCBiaW5kTmF0aXZlVGVsZW1ldHJ5UHJvdmlkZXIsIHJlZ2lzdGVyTmF0aXZlU3BhblByb2Nlc3NvciwgZGVmZXJyZWROYXRpdmVUcmFjZXJQcm92aWRlciB9IGZyb20gXCIuL3NyYy90ZWxlbWV0cnkudHNcIjtcbmV4cG9ydCB0eXBlIHsgTmF0aXZlSHR0cFRlbGVtZXRyeU9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvdGVsZW1ldHJ5LnRzXCI7XG5leHBvcnQgeyBkZWZpbmVPcGVyYXRpb25zLCB0b29sUmVnaXN0cnlGcm9tT3BlcmF0aW9ucyB9IGZyb20gXCIuL3NyYy90b29sLW9wZXJhdGlvbnMudHNcIjtcbmV4cG9ydCB0eXBlIHsgQXBwS2l0VG9vbE1ldGEsIEFwcEtpdE9wZXJhdGlvblNjaGVtYU1ldGEsIEFwcEtpdE9wZXJhdGlvbiB9IGZyb20gXCIuL3NyYy90b29sLW9wZXJhdGlvbnMudHNcIjtcbmV4cG9ydCB7IFRvb2xSZWdpc3RyeVBsdWdpbiB9IGZyb20gXCIuL3NyYy90b29sLXByb3ZpZGVyLnRzXCI7XG5leHBvcnQgdHlwZSB7IEFnZW50VG9vbFByb2dyZXNzT3B0aW9ucywgQWdlbnRUb29sRXhlY3V0aW9uQ29udGV4dCB9IGZyb20gXCIuL3NyYy90b29sLXByb3ZpZGVyLnRzXCI7XG5leHBvcnQgeyBuYW1lLCBlbnRyaWVzIH0gZnJvbSBcIi4vc3JjL3Rvb2xraXQtZW50cmllcy50c1wiO1xuIl19
41
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxtQkFBbUIsQ0FBQztBQUN0RCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFlBQVksTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEtBQUssWUFBWSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxVQUFVLE1BQU0scUJBQXFCLENBQUM7QUFDbEQsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEtBQUssV0FBVyxNQUFNLHNCQUFzQixDQUFDO0FBQ3BELE9BQU8sS0FBSyxnQkFBZ0IsTUFBTSw0QkFBNEIsQ0FBQztBQUMvRCxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxXQUFXLE1BQU0sdUJBQXVCLENBQUM7QUFDckQsT0FBTyxLQUFLLGVBQWUsTUFBTSwyQkFBMkIsQ0FBQztBQUM3RCxPQUFPLEtBQUssY0FBYyxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsT0FBTyxLQUFLLFdBQVcsTUFBTSx1QkFBdUIsQ0FBQztBQUNyRCxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxjQUFjLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxLQUFLLFlBQVksTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEtBQUssY0FBYyxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxhQUFhLEVBQUUsU0FBUyxFQUFFLHNCQUFzQixFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFM0gsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzNFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxxQkFBcUIsRUFBRSxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU3SSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFaEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXZGLE9BQU8sRUFBRSxjQUFjLEVBQUUscUJBQXFCLEVBQUUsbUJBQW1CLEVBQUUsa0JBQWtCLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFFLG1CQUFtQixFQUFFLDZCQUE2QixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFeE0sT0FBTyxFQUFFLHdCQUF3QixFQUFFLHFCQUFxQixFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXhHLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsa0JBQWtCLEVBQUUseUJBQXlCLEVBQUUsa0JBQWtCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVqTixPQUFPLEVBQUUseUJBQXlCLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUU5RixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFckQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFL0QsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFbkUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLG9CQUFvQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDaEYsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTVGLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSwyQkFBMkIsRUFBRSxzQ0FBc0MsRUFBRSxrQkFBa0IsRUFBRSw0QkFBNEIsRUFBRSwyQkFBMkIsRUFBRSwyQkFBMkIsRUFBRSw0QkFBNEIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRXpRLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSwwQkFBMEIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRXhGLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRTVELE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sMEJBQTBCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBHRU5FUkFURUQgYnkgcHJvamVuIHdhdGNoIC0gRE8gTk9UIEVESVQuXG4vLyBSZWdlbmVyYXRlZCBmcm9tIHRoZSBleHBvcnRpbmcgbW9kdWxlcyBpbiAuL3NyYy5cbi8vIEhhbmQgZWRpdHMgYXJlIG92ZXJ3cml0dGVuIG9uIHRoZSBuZXh0IHdhdGNoOyB0aGlzIGZpbGUgaXMgcmVhZC1vbmx5LlxuXG5leHBvcnQgY29uc3QgUEFDS0FHRV9JREVOVElGSUVSID0gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9IFwiMC45LjE4N1wiO1xuZXhwb3J0ICogYXMgYXBwa2l0IGZyb20gXCIuL3NyYy9hcHBraXQudHNcIjtcbmV4cG9ydCAqIGFzIGJyYW5kQ29udGV4dCBmcm9tIFwiLi9zcmMvYnJhbmQtY29udGV4dC50c1wiO1xuZXhwb3J0ICogYXMgY2FjaGVTdG9yYWdlIGZyb20gXCIuL3NyYy9jYWNoZS1zdG9yYWdlLnRzXCI7XG5leHBvcnQgKiBhcyBkYXRhYnJpY2tzIGZyb20gXCIuL3NyYy9kYXRhYnJpY2tzLnRzXCI7XG5leHBvcnQgKiBhcyBpZGVudGl0eSBmcm9tIFwiLi9zcmMvaWRlbnRpdHkudHNcIjtcbmV4cG9ydCAqIGFzIGludGVyY2VwdG9yIGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0ICogYXMgbGFrZWJhc2VSZXNvbHZlciBmcm9tIFwiLi9zcmMvbGFrZWJhc2UtcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCAqIGFzIG1pZ3JhdGlvbiBmcm9tIFwiLi9zcmMvbWlncmF0aW9uLnRzXCI7XG5leHBvcnQgKiBhcyBvcGVuYXBpVG9vbCBmcm9tIFwiLi9zcmMvb3BlbmFwaS10b29sLnRzXCI7XG5leHBvcnQgKiBhcyBwbHVnaW5FeGVjdXRpb24gZnJvbSBcIi4vc3JjL3BsdWdpbi1leGVjdXRpb24udHNcIjtcbmV4cG9ydCAqIGFzIHBsdWdpblJlZ2lzdHJ5IGZyb20gXCIuL3NyYy9wbHVnaW4tcmVnaXN0cnkudHNcIjtcbmV4cG9ydCAqIGFzIHByb3Zpc2lvbiBmcm9tIFwiLi9zcmMvcHJvdmlzaW9uLnRzXCI7XG5leHBvcnQgKiBhcyByZXF1ZXN0VGFncyBmcm9tIFwiLi9zcmMvcmVxdWVzdC10YWdzLnRzXCI7XG5leHBvcnQgKiBhcyB0ZWxlbWV0cnkgZnJvbSBcIi4vc3JjL3RlbGVtZXRyeS50c1wiO1xuZXhwb3J0ICogYXMgdG9vbE9wZXJhdGlvbnMgZnJvbSBcIi4vc3JjL3Rvb2wtb3BlcmF0aW9ucy50c1wiO1xuZXhwb3J0ICogYXMgdG9vbFByb3ZpZGVyIGZyb20gXCIuL3NyYy90b29sLXByb3ZpZGVyLnRzXCI7XG5leHBvcnQgKiBhcyB0b29sa2l0RW50cmllcyBmcm9tIFwiLi9zcmMvdG9vbGtpdC1lbnRyaWVzLnRzXCI7XG5leHBvcnQgeyBkZWJ1Z0NhcHR1cmVFbmFibGVkLCBhdXRvQ29uZmlndXJlLCBjcmVhdGVBcHAsIHRyeUdldEV4ZWN1dGlvbkNvbnRleHQsIGVuc3VyZUluaXRpYWxpemVkIH0gZnJvbSBcIi4vc3JjL2FwcGtpdC50c1wiO1xuZXhwb3J0IHR5cGUgeyBBdXRvQ29uZmlndXJlTW9kZSwgRGVidWdDYXB0dXJlTW9kZSwgQ3JlYXRlQXBwQ29uZmlnLCBFeGVjdXRpb25Db250ZXh0TGlrZSwgV29ya3NwYWNlQ2xpZW50TGlrZSB9IGZyb20gXCIuL3NyYy9hcHBraXQudHNcIjtcbmV4cG9ydCB7IGxvYWRCcmFuZENvbnRleHQsIGdldEJyYW5kQ29udGV4dCB9IGZyb20gXCIuL3NyYy9icmFuZC1jb250ZXh0LnRzXCI7XG5leHBvcnQgeyBBcHBLaXRDYWNoZVN0b3JhZ2UsIGxvYWRQZXJzaXN0ZW50U3RvcmFnZSwgc29mdGVuSW5pdGlhbGl6ZSwgcHJvYmVTdG9yYWdlLCBjcmVhdGVBcHBLaXRDYWNoZVN0b3JhZ2UgfSBmcm9tIFwiLi9zcmMvY2FjaGUtc3RvcmFnZS50c1wiO1xuZXhwb3J0IHR5cGUgeyBBcHBLaXRDYWNoZVN0b3JhZ2VPcHRpb25zLCBQZXJzaXN0ZW50U3RvcmFnZUJhc2UgfSBmcm9tIFwiLi9zcmMvY2FjaGUtc3RvcmFnZS50c1wiO1xuZXhwb3J0IHsgdG9Db250ZXh0IH0gZnJvbSBcIi4vc3JjL2RhdGFicmlja3MudHNcIjtcbmV4cG9ydCB0eXBlIHsgQ29udGV4dExpa2UgfSBmcm9tIFwiLi9zcmMvZGF0YWJyaWNrcy50c1wiO1xuZXhwb3J0IHsgRmlsZXNDYWNoZU1hbmFnZXIsIEZpbGVzQ2FjaGVQbHVnaW4sIGZpbGVzQ2FjaGUgfSBmcm9tIFwiLi9zcmMvZmlsZXMtY2FjaGUudHNcIjtcbmV4cG9ydCB0eXBlIHsgRmlsZXNDYWNoZVBsdWdpbkNvbmZpZywgRmlsZXNDYWNoZVNjb3BlLCBGaWxlc0NhY2hlU291cmNlSWRlbnRpdHksIEZpbGVzQ2FjaGVFeHBvcnRzIH0gZnJvbSBcIi4vc3JjL2ZpbGVzLWNhY2hlLnRzXCI7XG5leHBvcnQgeyBJREVOVElUWV9NT0RFUywgREVGQVVMVF9JREVOVElUWV9NT0RFLCByZXNvbHZlSWRlbnRpdHlNb2RlLCByZXF1ZXN0QWNjZXNzVG9rZW4sIHJlcXVlc3RVc2VySWQsIHJlcXVlc3RVc2VyRW1haWwsIHVzZVNlcnZpY2VQcmluY2lwYWwsIGluc3RhbGxBc1VzZXJEZXZlbG9wbWVudFBhdGNoIH0gZnJvbSBcIi4vc3JjL2lkZW50aXR5LnRzXCI7XG5leHBvcnQgdHlwZSB7IElkZW50aXR5TW9kZSwgSGVhZGVyQmVhcmluZyB9IGZyb20gXCIuL3NyYy9pZGVudGl0eS50c1wiO1xuZXhwb3J0IHsgY3JlYXRlSW50ZXJjZXB0b3JDb250ZXh0LCBMaWZlY3ljbGVCcmlkZ2VQbHVnaW4sIGxpZmVjeWNsZUJyaWRnZSB9IGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0IHR5cGUgeyBMaWZlY3ljbGVFdmVudCwgTGlmZWN5Y2xlSGFuZGxlciwgUmVzb2x2ZWRBcHBFbnYsIEludGVyY2VwdG9yQ29udGV4dCwgSW50ZXJjZXB0b3IsIEludGVyY2VwdG9yUnVudGltZSB9IGZyb20gXCIuL3NyYy9pbnRlcmNlcHRvci50c1wiO1xuZXhwb3J0IHsgY2FwdHVyZVNlcnZpY2VQcmluY2lwYWxQb29sLCBwYXJzZVBvcnQsIHBhcnNlU3NsTW9kZSwgbmV4dFBvbGxEZWxheSwgcG9sbERlbGF5LCByZWFkTGFrZWJhc2VJbnB1dHMsIHJlc29sdmVMYWtlYmFzZUNvbm5lY3Rpb24sIGFwcGx5TGFrZWJhc2VUb0VudiwgYXBwbHlMYWtlYmFzZUVudiB9IGZyb20gXCIuL3NyYy9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuZXhwb3J0IHR5cGUgeyBMYWtlYmFzZVJlc29sdmVySW5wdXRzLCBMYWtlYmFzZUNvbm5lY3Rpb24gfSBmcm9tIFwiLi9zcmMvbGFrZWJhc2UtcmVzb2x2ZXIudHNcIjtcbmV4cG9ydCB7IGlzT3duZXJzaGlwTWlncmF0aW9uRXJyb3IsIGhhbmRsZU93bmVyc2hpcE1pZ3JhdGlvbkVycm9yIH0gZnJvbSBcIi4vc3JjL21pZ3JhdGlvbi50c1wiO1xuZXhwb3J0IHR5cGUgeyBPd25lcnNoaXBNaWdyYXRpb25FcnJvck9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvbWlncmF0aW9uLnRzXCI7XG5leHBvcnQgeyBvcGVuQXBpVG9vbHMgfSBmcm9tIFwiLi9zcmMvb3BlbmFwaS10b29sLnRzXCI7XG5leHBvcnQgdHlwZSB7IE9wZW5BcGlIdHRwTWV0aG9kLCBPcGVuQXBpVG9vbCwgT3BlbkFwaVRvb2xzT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9vcGVuYXBpLXRvb2wudHNcIjtcbmV4cG9ydCB7IHJ1blBsdWdpbkV4ZWN1dGlvbiB9IGZyb20gXCIuL3NyYy9wbHVnaW4tZXhlY3V0aW9uLnRzXCI7XG5leHBvcnQgdHlwZSB7IFJ1blBsdWdpbkV4ZWN1dGlvbk9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvcGx1Z2luLWV4ZWN1dGlvbi50c1wiO1xuZXhwb3J0IHsgZGF0YSwgaW5zdGFuY2UsIHJlcXVpcmUgfSBmcm9tIFwiLi9zcmMvcGx1Z2luLXJlZ2lzdHJ5LnRzXCI7XG5leHBvcnQgdHlwZSB7IFBsdWdpbkNvbnRleHRMaWtlIH0gZnJvbSBcIi4vc3JjL3BsdWdpbi1yZWdpc3RyeS50c1wiO1xuZXhwb3J0IHsgY2FjaGVHcmFudFN0YXRlbWVudHMsIHByb3Zpc2lvbkNhY2hlU2NoZW1hIH0gZnJvbSBcIi4vc3JjL3Byb3Zpc2lvbi50c1wiO1xuZXhwb3J0IHsgaW5qZWN0UmVxdWVzdFRhZywgaW5qZWN0UmVxdWVzdFRhZ3MsIGdldFJlcXVlc3RUYWdzIH0gZnJvbSBcIi4vc3JjL3JlcXVlc3QtdGFncy50c1wiO1xuZXhwb3J0IHR5cGUgeyBSZXF1ZXN0VGFnVmFsdWUgfSBmcm9tIFwiLi9zcmMvcmVxdWVzdC10YWdzLnRzXCI7XG5leHBvcnQgeyBVU0VSX1RSQUNFX0FUVFJJQlVURSwgZXhjbHVkZUh0dHBUZWxlbWV0cnlSZXF1ZXN0LCBleGNsdWRlVW5wYXJlbnRlZE91dGdvaW5nSHR0cFRlbGVtZXRyeSwgc3RhbXBIdHRwVHJhY2VVc2VyLCBjb25maWd1cmVOYXRpdmVIdHRwVGVsZW1ldHJ5LCBiaW5kTmF0aXZlVGVsZW1ldHJ5UHJvdmlkZXIsIHJlZ2lzdGVyTmF0aXZlU3BhblByb2Nlc3NvciwgZGVmZXJyZWROYXRpdmVUcmFjZXJQcm92aWRlciB9IGZyb20gXCIuL3NyYy90ZWxlbWV0cnkudHNcIjtcbmV4cG9ydCB0eXBlIHsgTmF0aXZlSHR0cFRlbGVtZXRyeU9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvdGVsZW1ldHJ5LnRzXCI7XG5leHBvcnQgeyBkZWZpbmVPcGVyYXRpb25zLCB0b29sUmVnaXN0cnlGcm9tT3BlcmF0aW9ucyB9IGZyb20gXCIuL3NyYy90b29sLW9wZXJhdGlvbnMudHNcIjtcbmV4cG9ydCB0eXBlIHsgQXBwS2l0VG9vbE1ldGEsIEFwcEtpdE9wZXJhdGlvblNjaGVtYU1ldGEsIEFwcEtpdE9wZXJhdGlvbiB9IGZyb20gXCIuL3NyYy90b29sLW9wZXJhdGlvbnMudHNcIjtcbmV4cG9ydCB7IFRvb2xSZWdpc3RyeVBsdWdpbiB9IGZyb20gXCIuL3NyYy90b29sLXByb3ZpZGVyLnRzXCI7XG5leHBvcnQgdHlwZSB7IEFnZW50VG9vbFByb2dyZXNzT3B0aW9ucywgQWdlbnRUb29sRXhlY3V0aW9uQ29udGV4dCB9IGZyb20gXCIuL3NyYy90b29sLXByb3ZpZGVyLnRzXCI7XG5leHBvcnQgeyBuYW1lLCBlbnRyaWVzIH0gZnJvbSBcIi4vc3JjL3Rvb2xraXQtZW50cmllcy50c1wiO1xuIl19
@@ -54,12 +54,19 @@ type AppKitPlugins = NonNullable<AppKitCreateAppConfig["plugins"]>;
54
54
  * there: the app SP cannot grant on the cache schema anyway.
55
55
  */
56
56
  export type AutoConfigureMode = "env" | "provision";
57
+ /** Automatic browser debug-capture registration policy. */
58
+ export type DebugCaptureMode = "auto" | boolean;
57
59
  /** AppKit's `createApp` config plus the dbx-tools auto-configuration switch. */
58
60
  export type CreateAppConfig<T extends AppKitPlugins = AppKitPlugins> = Omit<AppKitCreateAppConfig, "plugins" | "onPluginsReady"> & {
59
61
  plugins?: T;
60
62
  onPluginsReady?: (appkit: PluginMap<T>) => void | Promise<void>;
61
63
  /** Auto-configuration to run before AppKit boots. Defaults to `"provision"`. */
62
64
  autoConfigure?: AutoConfigureMode | false;
65
+ /**
66
+ * Register AppKit browser debug-capture routes. `"auto"` (the default)
67
+ * enables them only when `NODE_ENV` is `"development"`.
68
+ */
69
+ debug?: DebugCaptureMode;
63
70
  /**
64
71
  * One or many {@link Interceptor}s handed an {@link InterceptorContext} once
65
72
  * auto-configuration has computed the env. Each receives the resolved env, an
@@ -68,6 +75,8 @@ export type CreateAppConfig<T extends AppKitPlugins = AppKitPlugins> = Omit<AppK
68
75
  */
69
76
  interceptor?: Interceptor | Interceptor[];
70
77
  };
78
+ /** Resolve the `createApp.debug` policy for one Node environment. */
79
+ export declare function debugCaptureEnabled(mode: DebugCaptureMode | undefined, nodeEnvironment?: string | undefined): boolean;
71
80
  /**
72
81
  * Run enabled auto-configuration steps without calling AppKit's `createApp`.
73
82
  *
package/lib/src/appkit.js CHANGED
@@ -28,10 +28,12 @@
28
28
  */
29
29
  import { createApp as appkitCreateApp, getExecutionContext, InitializationError, } from "@databricks/appkit";
30
30
  import { resolveProfile } from "@dbx-tools/auth";
31
+ import { DEBUG_CAPTURE_PLUGIN_NAME } from "@dbx-tools/shared-appkit/debug";
31
32
  import { log, tieAbortSignal } from "@dbx-tools/shared-core";
32
33
  import { resolveAutoConfigurePolicy } from "./_auto-configure.js";
33
34
  import { loadBrandContext } from "./brand-context.js";
34
35
  import { createAppKitCacheStorage } from "./cache-storage.js";
36
+ import { debugCapture } from "./debug/plugin.js";
35
37
  import { installAsUserDevelopmentPatch } from "./identity.js";
36
38
  import { createInterceptorContext, lifecycleBridge, } from "./interceptor.js";
37
39
  import { applyLakebaseEnv } from "./lakebase-resolver.js";
@@ -54,6 +56,14 @@ function usesPlugin(config, name) {
54
56
  function pluginNames(config) {
55
57
  return (config?.plugins ?? []).map((entry) => entry.name);
56
58
  }
59
+ /** Resolve the `createApp.debug` policy for one Node environment. */
60
+ export function debugCaptureEnabled(mode, nodeEnvironment = process.env.NODE_ENV) {
61
+ if (mode === true)
62
+ return true;
63
+ if (mode === false)
64
+ return false;
65
+ return nodeEnvironment === "development";
66
+ }
57
67
  /**
58
68
  * Run enabled auto-configuration steps without calling AppKit's `createApp`.
59
69
  *
@@ -225,6 +235,7 @@ export async function createApp(config) {
225
235
  });
226
236
  const appConfig = { ...config };
227
237
  delete appConfig.autoConfigure;
238
+ delete appConfig.debug;
228
239
  delete appConfig.interceptor;
229
240
  const onPluginsReady = appConfig.onPluginsReady;
230
241
  appConfig.onPluginsReady = async (app) => {
@@ -243,6 +254,13 @@ export async function createApp(config) {
243
254
  persistent: storage.isPersistent(),
244
255
  });
245
256
  }
257
+ if (debugCaptureEnabled(config?.debug) && !usesPlugin(config, DEBUG_CAPTURE_PLUGIN_NAME)) {
258
+ appConfig.plugins = [...(appConfig.plugins ?? []), debugCapture()];
259
+ logger.debug("createApp: browser debug capture injected", {
260
+ mode: config?.debug ?? "auto",
261
+ nodeEnvironment: process.env.NODE_ENV,
262
+ });
263
+ }
246
264
  if (interceptors.length === 0) {
247
265
  logger.debug("createApp: no interceptors; delegating to AppKit createApp", {
248
266
  plugins: pluginNames(appConfig),
@@ -325,4 +343,4 @@ export async function ensureInitialized() {
325
343
  await createApp({ plugins: [], autoConfigure: false });
326
344
  logger.debug("ensureInitialized: bare AppKit initialization complete");
327
345
  }
328
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwa2l0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwcGtpdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMkJHO0FBRUgsT0FBTyxFQUNMLFNBQVMsSUFBSSxlQUFlLEVBQzVCLG1CQUFtQixFQUNuQixtQkFBbUIsR0FDcEIsTUFBTSxvQkFBb0IsQ0FBQztBQUk1QixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDakQsT0FBTyxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU3RCxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN0RCxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDOUQsT0FBTyxFQUNMLHdCQUF3QixFQUd4QixlQUFlLEdBRWhCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUFFLGdCQUFnQixFQUEyQixNQUFNLHdCQUF3QixDQUFDO0FBQ25GLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3RELE9BQU8sRUFDTCwyQkFBMkIsRUFDM0IsNEJBQTRCLEVBQzVCLGtCQUFrQixHQUNuQixNQUFNLGdCQUFnQixDQUFDO0FBRXhCLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7QUE4Q3BDLE1BQU0sZUFBZSxHQUFHLFVBQVUsQ0FBQztBQUVuQzs7Ozs7O0dBTUc7QUFDSCxNQUFNLHlCQUF5QixHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUM7QUFFOUMsU0FBUyxVQUFVLENBQ2pCLE1BQXNDLEVBQ3RDLElBQVk7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LEVBQUUsQ0FBQztZQUNoQixPQUFPLEdBQUcsQ0FBQztRQUNiLENBQUM7SUFDSCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLElBQUksQ0FBQyxDQUFDLEtBQUssWUFBWSxtQkFBbUIsQ0FBQyxFQUFFLENBQUM7WUFDNUMsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sU0FBUyxDQUFDO0FBQ25CLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsaUJBQWlCO0lBQ3JDLElBQUksc0JBQXNCLEVBQUUsRUFBRSxDQUFDO1FBQzdCLE1BQU0sQ0FBQyxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQztRQUN2RCxPQUFPO0lBQ1QsQ0FBQztJQUNELE1BQU0sQ0FBQyxLQUFLLENBQUMsNENBQTRDLENBQUMsQ0FBQztJQUMzRCxNQUFNLFNBQVMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDdkQsTUFBTSxDQUFDLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO0FBQ3pFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEFwcEtpdCBydW50aW1lIGdsdWU6IHRoZSBhdXRvLWNvbmZpZ3VyaW5nIGBjcmVhdGVBcHBgIGRyb3AtaW4sIHBsdXMgdGhlXG4gKiBwZXItcmVxdWVzdCBleGVjdXRpb24gY29udGV4dCBoZWxwZXJzIGFuZCB0eXBlcyBkZXJpdmVkIGZyb20gaXQuXG4gKlxuICogYGNyZWF0ZUFwcGAgcnVucyBkYngtdG9vbHMgYXV0by1jb25maWd1cmF0aW9uLCB0aGVuIGRlbGVnYXRlcyB0byBBcHBLaXQncyBvd25cbiAqIGBjcmVhdGVBcHBgIHdpdGggdGhlIHNhbWUgYXJndW1lbnRzIGFuZCB0aGUgc2FtZSB0eXBlZCBwbHVnaW4tZXhwb3J0IG1hcC5cbiAqIERyb3AgaXQgaW4gYXMgYSBvbmUtZm9yLW9uZSByZXBsYWNlbWVudDpcbiAqXG4gKiBgYGB0c1xuICogaW1wb3J0IHsgbGFrZWJhc2UsIHNlcnZlciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbiAqIGltcG9ydCB7IGFwcGtpdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuICpcbiAqIGF3YWl0IGFwcGtpdC5jcmVhdGVBcHAoeyBwbHVnaW5zOiBbc2VydmVyKCksIGxha2ViYXNlKCldIH0pO1xuICogYGBgXG4gKlxuICogQXV0by1jb25maWd1cmF0aW9uIHJ1bnMgQkVGT1JFIGRlbGVnYXRpbmcgc28gcGx1Z2lucyBzZWUgYSBmdWxseSBwb3B1bGF0ZWRcbiAqIGBwcm9jZXNzLmVudmAgZHVyaW5nIHRoZWlyIHN5bmNocm9ub3VzIGBzZXR1cCgpYC4gTGFrZWJhc2UgUG9zdGdyZXMgcmVzb2x1dGlvblxuICogcnVucyB3aGVuIGEgbmF0aXZlIGBsYWtlYmFzZWAgb3IgYGRhdGFiYXNlYCBwbHVnaW4gaXMgcHJlc2VudCwgb3Igd2hlblxuICoge0BsaW5rIEF1dG9Db25maWd1cmVNb2RlfSBpcyBzZXQgZXhwbGljaXRseSBvbiB0aGUgY29uZmlnIG9iamVjdC5cbiAqXG4gKiBgZ2V0RXhlY3V0aW9uQ29udGV4dCgpYCBpcyBBcHBLaXQncyBvd24gYWNjZXNzb3IgZm9yIHRoZSBPQk8tc2NvcGVkIHdvcmtzcGFjZVxuICogY2xpZW50ICsgcmVxdWVzdCBtZXRhZGF0YTsgdGhlIHdyYXBwZXJzIGhlcmUgbWFrZSBpdCBzYWZlIHRvIGNhbGwgb3V0c2lkZSBhXG4gKiByZXF1ZXN0IHNjb3BlICh7QGxpbmsgdHJ5R2V0RXhlY3V0aW9uQ29udGV4dH0pIGFuZCB0byBsYXppbHkgYm9vdCBhIGJhcmUgYXBwXG4gKiAoe0BsaW5rIGVuc3VyZUluaXRpYWxpemVkfSksIGFuZCByZS1leHBvcnQgdGhlIGRlcml2ZWQgdHlwZXMgc28gYWRkLW9uXG4gKiBwYWNrYWdlcyBjYW4gdHlwZSBhIGNvbnRleHQgLyBjbGllbnQgd2l0aG91dCByZS1kZXJpdmluZyB0aGVtIGlubGluZS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHtcbiAgY3JlYXRlQXBwIGFzIGFwcGtpdENyZWF0ZUFwcCxcbiAgZ2V0RXhlY3V0aW9uQ29udGV4dCxcbiAgSW5pdGlhbGl6YXRpb25FcnJvcixcbn0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuLy8gQXBwS2l0J3Mgcm9vdCBiYXJyZWwgcmUtZXhwb3J0cyBgUGx1Z2luRGF0YWAgYnV0IG5vdCBgUGx1Z2luTWFwYDsgdGhlIHBhY2thZ2Vcbi8vIHB1Ymxpc2hlcyB0aGlzIHN1YnBhdGggZm9yIGV4YWN0bHkgdGhhdCB0eXBlLlxuaW1wb3J0IHR5cGUgeyBQbHVnaW5NYXAgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0L2Rpc3Qvc2hhcmVkL3NyYy9wbHVnaW5cIjtcbmltcG9ydCB7IHJlc29sdmVQcm9maWxlIH0gZnJvbSBcIkBkYngtdG9vbHMvYXV0aFwiO1xuaW1wb3J0IHsgbG9nLCB0aWVBYm9ydFNpZ25hbCB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5cbmltcG9ydCB7IHJlc29sdmVBdXRvQ29uZmlndXJlUG9saWN5IH0gZnJvbSBcIi4vX2F1dG8tY29uZmlndXJlLnRzXCI7XG5pbXBvcnQgeyBsb2FkQnJhbmRDb250ZXh0IH0gZnJvbSBcIi4vYnJhbmQtY29udGV4dC50c1wiO1xuaW1wb3J0IHsgY3JlYXRlQXBwS2l0Q2FjaGVTdG9yYWdlIH0gZnJvbSBcIi4vY2FjaGUtc3RvcmFnZS50c1wiO1xuaW1wb3J0IHsgaW5zdGFsbEFzVXNlckRldmVsb3BtZW50UGF0Y2ggfSBmcm9tIFwiLi9pZGVudGl0eS50c1wiO1xuaW1wb3J0IHtcbiAgY3JlYXRlSW50ZXJjZXB0b3JDb250ZXh0LFxuICB0eXBlIEludGVyY2VwdG9yLFxuICB0eXBlIEludGVyY2VwdG9yUnVudGltZSxcbiAgbGlmZWN5Y2xlQnJpZGdlLFxuICB0eXBlIFJlc29sdmVkQXBwRW52LFxufSBmcm9tIFwiLi9pbnRlcmNlcHRvci50c1wiO1xuaW1wb3J0IHsgYXBwbHlMYWtlYmFzZUVudiwgdHlwZSBMYWtlYmFzZUNvbm5lY3Rpb24gfSBmcm9tIFwiLi9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuaW1wb3J0IHsgcHJvdmlzaW9uQ2FjaGVTY2hlbWEgfSBmcm9tIFwiLi9wcm92aXNpb24udHNcIjtcbmltcG9ydCB7XG4gIGJpbmROYXRpdmVUZWxlbWV0cnlQcm92aWRlcixcbiAgY29uZmlndXJlTmF0aXZlSHR0cFRlbGVtZXRyeSxcbiAgc3RhbXBIdHRwVHJhY2VVc2VyLFxufSBmcm9tIFwiLi90ZWxlbWV0cnkudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImFwcGtpdFwiKTtcblxudHlwZSBBcHBLaXRDcmVhdGVBcHBDb25maWcgPSBOb25OdWxsYWJsZTxQYXJhbWV0ZXJzPHR5cGVvZiBhcHBraXRDcmVhdGVBcHA+WzBdPjtcbnR5cGUgQXBwS2l0UGx1Z2lucyA9IE5vbk51bGxhYmxlPEFwcEtpdENyZWF0ZUFwcENvbmZpZ1tcInBsdWdpbnNcIl0+O1xuXG4vKipcbiAqIFdoYXQgYXV0by1jb25maWd1cmF0aW9uIGRvZXMgYmVmb3JlIEFwcEtpdCBib290cy5cbiAqXG4gKiAtIGBcInByb3Zpc2lvblwiYDogcmVzb2x2ZSB0aGUgTGFrZWJhc2UgY29ubmVjdGlvbiBpbnRvIGBwcm9jZXNzLmVudmAsIHRoZW5cbiAqICAgZ3JhbnQgdGhlIEFwcEtpdCBjYWNoZSBzY2hlbWEgdG8gdGhlIGNvbm5lY3Rpbmcgcm9sZS5cbiAqIC0gYFwiZW52XCJgOiByZXNvbHZlIHRoZSBMYWtlYmFzZSBjb25uZWN0aW9uIGludG8gYHByb2Nlc3MuZW52YCBvbmx5LlxuICpcbiAqIE9taXQgaXQgdG8gcmVzb2x2ZSBkYXRhYmFzZSBlbnZpcm9ubWVudCB3aGVuIGEgbmF0aXZlIGBsYWtlYmFzZWAgb3JcbiAqIGBkYXRhYmFzZWAgcGx1Z2luIGlzIHJlZ2lzdGVyZWQuIEltcGxpY2l0IGNhY2hlLXNjaGVtYSBncmFudHMgcmVtYWluIGdhdGVkIG9uXG4gKiBgbGFrZWJhc2VgOyBgZGF0YWJhc2VgIG93bnMgaXRzIG93biBwb29sIGFuZCBkb2VzIG5vdCBicm9hZGVuIGdyYW50cy4gU2V0IHRoZVxuICogbW9kZSBleHBsaWNpdGx5IHRvIHJ1biByZWdhcmRsZXNzIG9mIHRoZSBwbHVnaW4gbGlzdCwgb3IgcGFzcyBgZmFsc2VgIHRvIHNraXBcbiAqIGF1dG8tY29uZmlndXJhdGlvbiBlbnRpcmVseS5cbiAqXG4gKiBTZXQgaXQgRVhQTElDSVRMWSBvbiBhbiBhcHAgdGhhdCBoYXMgbm8gYGxha2ViYXNlKClgIHBsdWdpbiBidXQgc3RpbGwgd2FudHNcbiAqIEFwcEtpdCdzIFBFUlNJU1RFTlQgY2FjaGUuIEFwcEtpdCBwaWNrcyBMYWtlYmFzZSBmb3IgYENhY2hlTWFuYWdlcmAgb25seSB3aGVuXG4gKiBgY3JlYXRlTGFrZWJhc2VQb29sKClgIGNhbiBidWlsZCBhIHBvb2wsIGFuZCB0aGF0IHJlYWRzIGBMQUtFQkFTRV9FTkRQT0lOVGAgL1xuICogYFBHSE9TVGAgLyBgUEdEQVRBQkFTRWAgc3RyYWlnaHQgZnJvbSBgcHJvY2Vzcy5lbnZgIC0gc28gd2l0aG91dCB0aGlzIHN0ZXAgdGhlXG4gKiBjYWNoZSBzaWxlbnRseSBmYWxscyBiYWNrIHRvIGluLW1lbW9yeSwgYW5kIGFueXRoaW5nIGl0IGhvbGRzIChhIHNlc3Npb25cbiAqIHNpZ25pbmcga2V5LCBhIG9uZS10aW1lIGNvZGUpIGlzIGxvc3Qgb24gcmVzdGFydC4gYFwiZW52XCJgIGlzIHRoZSByaWdodCBtb2RlXG4gKiB0aGVyZTogdGhlIGFwcCBTUCBjYW5ub3QgZ3JhbnQgb24gdGhlIGNhY2hlIHNjaGVtYSBhbnl3YXkuXG4gKi9cbmV4cG9ydCB0eXBlIEF1dG9Db25maWd1cmVNb2RlID0gXCJlbnZcIiB8IFwicHJvdmlzaW9uXCI7XG5cbi8qKiBBcHBLaXQncyBgY3JlYXRlQXBwYCBjb25maWcgcGx1cyB0aGUgZGJ4LXRvb2xzIGF1dG8tY29uZmlndXJhdGlvbiBzd2l0Y2guICovXG5leHBvcnQgdHlwZSBDcmVhdGVBcHBDb25maWc8VCBleHRlbmRzIEFwcEtpdFBsdWdpbnMgPSBBcHBLaXRQbHVnaW5zPiA9IE9taXQ8XG4gIEFwcEtpdENyZWF0ZUFwcENvbmZpZyxcbiAgXCJwbHVnaW5zXCIgfCBcIm9uUGx1Z2luc1JlYWR5XCJcbj4gJiB7XG4gIHBsdWdpbnM/OiBUO1xuICBvblBsdWdpbnNSZWFkeT86IChhcHBraXQ6IFBsdWdpbk1hcDxUPikgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG4gIC8qKiBBdXRvLWNvbmZpZ3VyYXRpb24gdG8gcnVuIGJlZm9yZSBBcHBLaXQgYm9vdHMuIERlZmF1bHRzIHRvIGBcInByb3Zpc2lvblwiYC4gKi9cbiAgYXV0b0NvbmZpZ3VyZT86IEF1dG9Db25maWd1cmVNb2RlIHwgZmFsc2U7XG4gIC8qKlxuICAgKiBPbmUgb3IgbWFueSB7QGxpbmsgSW50ZXJjZXB0b3J9cyBoYW5kZWQgYW4ge0BsaW5rIEludGVyY2VwdG9yQ29udGV4dH0gb25jZVxuICAgKiBhdXRvLWNvbmZpZ3VyYXRpb24gaGFzIGNvbXB1dGVkIHRoZSBlbnYuIEVhY2ggcmVjZWl2ZXMgdGhlIHJlc29sdmVkIGVudiwgYW5cbiAgICogQXBwS2l0IGxpZmVjeWNsZSBob29rLiBTZWUgYC4vaW50ZXJjZXB0b3JgLiBUaGUgdHVubmVsIGlzIHRoZSBwcmltYXJ5XG4gICAqIGNvbnN1bWVyLlxuICAgKi9cbiAgaW50ZXJjZXB0b3I/OiBJbnRlcmNlcHRvciB8IEludGVyY2VwdG9yW107XG59O1xuXG5jb25zdCBMQUtFQkFTRV9QTFVHSU4gPSBcImxha2ViYXNlXCI7XG5cbi8qKlxuICogVXBwZXIgYm91bmQgb24gYm9vdC10aW1lIGF1dG8tY29uZmlndXJhdGlvbi4gSXQgcnVucyBhcyB0aGUgc2VydmljZSBwcmluY2lwYWxcbiAqIGJlZm9yZSBhbnkgcGx1Z2luIGlzIGNvbnN0cnVjdGVkLCBzbyBpdCBzaXRzIG91dHNpZGUgQXBwS2l0J3MgaW50ZXJjZXB0b3JcbiAqIGNoYWluIGFuZCBpbmhlcml0cyBubyB0aW1lb3V0LCByZXRyeSwgb3IgdGVsZW1ldHJ5IGZyb20gaXQuIFRoZSBidWRnZXQgY292ZXJzXG4gKiB0aGUgcmVzb2x2ZXIncyBvd24gd29yc3QgY2FzZSAoY3JlYXRlIGEgcHJvamVjdCwgdGhlbiB3YWl0IGZvciBpdHMgZW5kcG9pbnQpXG4gKiBwbHVzIHRoZSBjYWNoZS1zY2hlbWEgZ3JhbnRzLlxuICovXG5jb25zdCBBVVRPX0NPTkZJR1VSRV9USU1FT1VUX01TID0gMTEgKiA2MF8wMDA7XG5cbmZ1bmN0aW9uIHVzZXNQbHVnaW48VCBleHRlbmRzIEFwcEtpdFBsdWdpbnM+KFxuICBjb25maWc6IENyZWF0ZUFwcENvbmZpZzxUPiB8IHVuZGVmaW5lZCxcbiAgbmFtZTogc3RyaW5nLFxuKTogYm9vbGVhbiB7XG4gIHJldHVybiBCb29sZWFuKGNvbmZpZz8ucGx1Z2lucz8uc29tZSgoZW50cnkpID0+IGVudHJ5Lm5hbWUgPT09IG5hbWUpKTtcbn1cblxuLyoqIFBsdWdpbiBuYW1lcyBmb3IgYm9vdCBsb2dzIChvcmRlciBwcmVzZXJ2ZWQpLiAqL1xuZnVuY3Rpb24gcGx1Z2luTmFtZXMoY29uZmlnOiBDcmVhdGVBcHBDb25maWcgfCB1bmRlZmluZWQpOiBzdHJpbmdbXSB7XG4gIHJldHVybiAoY29uZmlnPy5wbHVnaW5zID8/IFtdKS5tYXAoKGVudHJ5KSA9PiBlbnRyeS5uYW1lKTtcbn1cblxuLyoqXG4gKiBSdW4gZW5hYmxlZCBhdXRvLWNvbmZpZ3VyYXRpb24gc3RlcHMgd2l0aG91dCBjYWxsaW5nIEFwcEtpdCdzIGBjcmVhdGVBcHBgLlxuICpcbiAqIExha2ViYXNlIFBvc3RncmVzIHJlc29sdmVzIHdoZW4ge0BsaW5rIENyZWF0ZUFwcENvbmZpZy5hdXRvQ29uZmlndXJlfSBpcyBzZXRcbiAqIGV4cGxpY2l0bHkgb3IgYSBuYXRpdmUgYGxha2ViYXNlYC9gZGF0YWJhc2VgIHBsdWdpbiBpcyBsaXN0ZWQgaW5cbiAqIGBjb25maWcucGx1Z2luc2AuIGBzaWduYWxgIGNhbmNlbHMgdGhlIHJlc29sdXRpb247IGl0IGlzIGNvbWJpbmVkIHdpdGggYW5cbiAqIGludGVybmFsIGJvb3QgdGltZW91dCBlaXRoZXIgd2F5LlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgeyBhcHBraXQgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbiAqXG4gKiAvLyBQb3B1bGF0ZSBQR0hPU1QgLyBQR0RBVEFCQVNFIC8gTEFLRUJBU0VfRU5EUE9JTlQgd2l0aG91dCBib290aW5nIEFwcEtpdC5cbiAqIGF3YWl0IGFwcGtpdC5hdXRvQ29uZmlndXJlKHsgYXV0b0NvbmZpZ3VyZTogXCJlbnZcIiB9KTtcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGF1dG9Db25maWd1cmU8VCBleHRlbmRzIEFwcEtpdFBsdWdpbnM+KFxuICBjb25maWc/OiBDcmVhdGVBcHBDb25maWc8VD4sXG4gIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuKTogUHJvbWlzZTxMYWtlYmFzZUNvbm5lY3Rpb24gfCB1bmRlZmluZWQ+IHtcbiAgY29uc3QgYnVuZGxlUHJvZmlsZSA9IGFwcGx5RGVmYXVsdFByb2ZpbGUoKTtcbiAgY29uc3QgcGx1Z2lucyA9IHBsdWdpbk5hbWVzKGNvbmZpZyk7XG4gIGNvbnN0IHBvbGljeSA9IHJlc29sdmVBdXRvQ29uZmlndXJlUG9saWN5KHBsdWdpbnMsIGNvbmZpZz8uYXV0b0NvbmZpZ3VyZSk7XG4gIGxvZ2dlci5kZWJ1ZyhcImF1dG9Db25maWd1cmU6IHN0YXJ0XCIsIHtcbiAgICAuLi5wb2xpY3ksXG4gICAgcGx1Z2lucyxcbiAgICB0aW1lb3V0TXM6IEFVVE9fQ09ORklHVVJFX1RJTUVPVVRfTVMsXG4gICAgY2FsbGVyU2lnbmFsOiBCb29sZWFuKHNpZ25hbCksXG4gIH0pO1xuXG4gIGlmICghcG9saWN5LnNob3VsZFJlc29sdmUpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJhdXRvQ29uZmlndXJlOiBza2lwXCIsIHsgLi4ucG9saWN5LCBwbHVnaW5zIH0pO1xuICAgIGxvZ2dlci5pbmZvKFwicmVhZHlcIiwge1xuICAgICAgYXV0b0NvbmZpZ3VyZTogcG9saWN5Lm1vZGUsXG4gICAgICBsYWtlYmFzZVBsdWdpblByZXNlbnQ6IHBvbGljeS5sYWtlYmFzZVBsdWdpblByZXNlbnQsXG4gICAgICBkYXRhYmFzZVBsdWdpblByZXNlbnQ6IHBvbGljeS5kYXRhYmFzZVBsdWdpblByZXNlbnQsXG4gICAgICBwcm92aXNpb25lZDogZmFsc2UsXG4gICAgICBza2lwcGVkUmVhc29uOiBwb2xpY3kuc2tpcHBlZFJlYXNvbixcbiAgICB9KTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgdGllQWJvcnRTaWduYWwoY29udHJvbGxlciwgc2lnbmFsKTtcbiAgdGllQWJvcnRTaWduYWwoY29udHJvbGxlciwgQWJvcnRTaWduYWwudGltZW91dChBVVRPX0NPTkZJR1VSRV9USU1FT1VUX01TKSk7XG5cbiAgbG9nZ2VyLmRlYnVnKFwiYXV0b0NvbmZpZ3VyZTogcmVzb2x2ZSBsYWtlYmFzZVwiLCB7XG4gICAgcHJvdmlzaW9uOiBwb2xpY3kucHJvdmlzaW9uLFxuICAgIG1vZGU6IHBvbGljeS5tb2RlLFxuICB9KTtcbiAgY29uc3QgcmVzb2x2ZWQgPSBhd2FpdCBhdXRvQ29uZmlndXJlTGFrZWJhc2UocG9saWN5LnByb3Zpc2lvbiwgY29udHJvbGxlci5zaWduYWwsIGJ1bmRsZVByb2ZpbGUpO1xuICBsb2dnZXIuZGVidWcoXCJhdXRvQ29uZmlndXJlOiBkb25lXCIsIHtcbiAgICBtb2RlOiBwb2xpY3kubW9kZSxcbiAgICBsYWtlYmFzZVBsdWdpblByZXNlbnQ6IHBvbGljeS5sYWtlYmFzZVBsdWdpblByZXNlbnQsXG4gICAgZGF0YWJhc2VQbHVnaW5QcmVzZW50OiBwb2xpY3kuZGF0YWJhc2VQbHVnaW5QcmVzZW50LFxuICAgIHByb3Zpc2lvbmVkOiBwb2xpY3kucHJvdmlzaW9uLFxuICAgIC4uLnJlZGFjdExha2ViYXNlQ29ubmVjdGlvbihyZXNvbHZlZCksXG4gIH0pO1xuICBsb2dnZXIuaW5mbyhcInJlYWR5XCIsIHtcbiAgICBhdXRvQ29uZmlndXJlOiBwb2xpY3kubW9kZSxcbiAgICBsYWtlYmFzZVBsdWdpblByZXNlbnQ6IHBvbGljeS5sYWtlYmFzZVBsdWdpblByZXNlbnQsXG4gICAgZGF0YWJhc2VQbHVnaW5QcmVzZW50OiBwb2xpY3kuZGF0YWJhc2VQbHVnaW5QcmVzZW50LFxuICAgIHByb3Zpc2lvbmVkOiBwb2xpY3kucHJvdmlzaW9uLFxuICB9KTtcbiAgcmV0dXJuIHJlc29sdmVkO1xufVxuXG4vKipcbiAqIFJlc29sdmUgTGFrZWJhc2UgUG9zdGdyZXMgY29ubmVjdGlvbiBpbmZvLCB3cml0ZSB0aGUgcmVzb2x2ZWQgdmFsdWVzIHRvXG4gKiBgcHJvY2Vzcy5lbnZgLCBhbmQgcmV0dXJuIHRoZSByZWNvcmQuIFVzZWQgYnkge0BsaW5rIGF1dG9Db25maWd1cmV9OyBjYWxsXG4gKiB7QGxpbmsgYXBwbHlMYWtlYmFzZUVudn0gZGlyZWN0bHkgd2hlbiBmaW5lciBjb250cm9sIGlzIG5lZWRlZCAoYSBkaWZmZXJlbnRcbiAqIGBhdXRvQ3JlYXRlYCBwb2xpY3ksIG9yIGEgY2FsbGVyIHRoYXQgd2FudHMgdGhlIGVudiB3aXRob3V0IGJvb3RpbmcgQXBwS2l0KS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gYXV0b0NvbmZpZ3VyZUxha2ViYXNlKFxuICBwcm92aXNpb246IGJvb2xlYW4sXG4gIHNpZ25hbDogQWJvcnRTaWduYWwsXG4gIGJ1bmRsZVByb2ZpbGU/OiBzdHJpbmcsXG4pOiBQcm9taXNlPExha2ViYXNlQ29ubmVjdGlvbj4ge1xuICBsb2dnZXIuZGVidWcoXCJhdXRvQ29uZmlndXJlTGFrZWJhc2U6IGFwcGx5TGFrZWJhc2VFbnZcIik7XG4gIGNvbnN0IHsgcmVzb2x2ZWQsIHVzZXIgfSA9IGF3YWl0IGFwcGx5TGFrZWJhc2VFbnYoeyBidW5kbGVQcm9maWxlIH0sIHNpZ25hbCk7XG4gIGxvZ2dlci5kZWJ1ZyhcImF1dG9Db25maWd1cmVMYWtlYmFzZTogZW52IGFwcGxpZWRcIiwge1xuICAgIC4uLnJlZGFjdExha2ViYXNlQ29ubmVjdGlvbihyZXNvbHZlZCksXG4gICAgdXNlcixcbiAgICBlbnY6IHtcbiAgICAgIExBS0VCQVNFX0VORFBPSU5UOiBwcm9jZXNzLmVudi5MQUtFQkFTRV9FTkRQT0lOVCxcbiAgICAgIFBHSE9TVDogcHJvY2Vzcy5lbnYuUEdIT1NULFxuICAgICAgUEdQT1JUOiBwcm9jZXNzLmVudi5QR1BPUlQsXG4gICAgICBQR0RBVEFCQVNFOiBwcm9jZXNzLmVudi5QR0RBVEFCQVNFLFxuICAgICAgUEdVU0VSOiBwcm9jZXNzLmVudi5QR1VTRVIsXG4gICAgICBQR1NTTE1PREU6IHByb2Nlc3MuZW52LlBHU1NMTU9ERSxcbiAgICB9LFxuICB9KTtcbiAgbG9nZ2VyLmluZm8oXCJlbnYgdXBkYXRlZFwiLCB7IC4uLnJlZGFjdExha2ViYXNlQ29ubmVjdGlvbihyZXNvbHZlZCksIHVzZXIgfSk7XG4gIGlmIChwcm92aXNpb24pIHtcbiAgICBsb2dnZXIuZGVidWcoXCJhdXRvQ29uZmlndXJlTGFrZWJhc2U6IHByb3Zpc2lvbkNhY2hlU2NoZW1hXCIsIHsgdXNlciB9KTtcbiAgICBhd2FpdCBwcm92aXNpb25DYWNoZVNjaGVtYSh1c2VyLCBsb2dnZXIpO1xuICAgIGxvZ2dlci5kZWJ1ZyhcImF1dG9Db25maWd1cmVMYWtlYmFzZTogcHJvdmlzaW9uQ2FjaGVTY2hlbWEgZG9uZVwiKTtcbiAgfSBlbHNlIHtcbiAgICBsb2dnZXIuZGVidWcoXCJhdXRvQ29uZmlndXJlTGFrZWJhc2U6IHNraXAgcHJvdmlzaW9uIChtb2RlPWVudilcIik7XG4gIH1cbiAgcmV0dXJuIHJlc29sdmVkO1xufVxuXG5mdW5jdGlvbiBhcHBseURlZmF1bHRQcm9maWxlKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGNvbmZpZ3VyZWQgPSBwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0NPTkZJR19QUk9GSUxFPy50cmltKCk7XG4gIGNvbnN0IHJlc29sdmVkID0gcmVzb2x2ZVByb2ZpbGUoY29uZmlndXJlZCA/IHsgcHJvZmlsZTogY29uZmlndXJlZCB9IDoge30pO1xuICBpZiAoIXJlc29sdmVkKSB7XG4gICAgZGVsZXRlIHByb2Nlc3MuZW52LkRBVEFCUklDS1NfQ09ORklHX1BST0ZJTEU7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICBwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0NPTkZJR19QUk9GSUxFID0gcmVzb2x2ZWQubmFtZTtcbiAgcmV0dXJuIHJlc29sdmVkLm5hbWU7XG59XG5cbi8qKiBXaGV0aGVyIGBjcmVhdGVBcHBgIHNob3VsZCBpbmplY3QgdGhlIGRlZmF1bHQgbWVtb3J5LWZpcnN0IGNhY2hlIHN0b3JhZ2UuICovXG5mdW5jdGlvbiBzaG91bGRJbmplY3RDYWNoZVN0b3JhZ2UoY29uZmlnOiBDcmVhdGVBcHBDb25maWcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgY29uc3QgY2FjaGUgPSBjb25maWc/LmNhY2hlO1xuICBpZiAoY2FjaGU/LmVuYWJsZWQgPT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG4gIGlmIChjYWNoZT8uc3RvcmFnZSkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gcmVkYWN0TGFrZWJhc2VDb25uZWN0aW9uKHJlc29sdmVkOiBMYWtlYmFzZUNvbm5lY3Rpb24pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIHJldHVybiB7XG4gICAgcHJvamVjdDogcmVzb2x2ZWQucHJvamVjdCxcbiAgICBicmFuY2g6IHJlc29sdmVkLmJyYW5jaCxcbiAgICBlbmRwb2ludDogcmVzb2x2ZWQuZW5kcG9pbnQsXG4gICAgZGF0YWJhc2U6IHJlc29sdmVkLmRhdGFiYXNlLFxuICAgIGhvc3Q6IHJlc29sdmVkLmhvc3QsXG4gICAgcG9ydDogcmVzb2x2ZWQucG9ydCxcbiAgICBzc2xNb2RlOiByZXNvbHZlZC5zc2xNb2RlLFxuICB9O1xufVxuXG4vKiogQnVpbGQgdGhlIHtAbGluayBSZXNvbHZlZEFwcEVudn0gaW50ZXJjZXB0b3JzIHJlYWQsIGZyb20gdGhlIGF1dG8tY29uZmlnIHJlc3VsdC4gKi9cbmZ1bmN0aW9uIHJlc29sdmVkQXBwRW52KGxha2ViYXNlOiBMYWtlYmFzZUNvbm5lY3Rpb24gfCB1bmRlZmluZWQpOiBSZXNvbHZlZEFwcEVudiB7XG4gIHJldHVybiB7XG4gICAgLi4uKGxha2ViYXNlID8geyBsYWtlYmFzZSB9IDoge30pLFxuICAgIC4uLihwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0hPU1QgPyB7IGRhdGFicmlja3NIb3N0OiBwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0hPU1QgfSA6IHt9KSxcbiAgfTtcbn1cblxuLyoqIE5vcm1hbGl6ZSB0aGUgYGludGVyY2VwdG9yPzogSW50ZXJjZXB0b3IgfCBJbnRlcmNlcHRvcltdYCBvcHRpb24gdG8gYW4gYXJyYXkuICovXG5mdW5jdGlvbiBpbnRlcmNlcHRvckxpc3QoaW50ZXJjZXB0b3I6IENyZWF0ZUFwcENvbmZpZ1tcImludGVyY2VwdG9yXCJdKTogSW50ZXJjZXB0b3JbXSB7XG4gIGlmICghaW50ZXJjZXB0b3IpIHJldHVybiBbXTtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoaW50ZXJjZXB0b3IpID8gaW50ZXJjZXB0b3IgOiBbaW50ZXJjZXB0b3JdO1xufVxuXG4vKipcbiAqIEF1dG8tY29uZmlndXJpbmcgZHJvcC1pbiBmb3IgQXBwS2l0J3MgYGNyZWF0ZUFwcGA6IHNhbWUgY29uZmlnLCBzYW1lIHR5cGVkXG4gKiBwbHVnaW4tZXhwb3J0IG1hcCwgd2l0aCB7QGxpbmsgYXV0b0NvbmZpZ3VyZX0gcnVuIGZpcnN0LlxuICpcbiAqIFdoZW4ge0BsaW5rIENyZWF0ZUFwcENvbmZpZy5pbnRlcmNlcHRvcn1zIGFyZSBnaXZlbiwgZWFjaCBpcyBpbnZva2VkIHdpdGggYW5cbiAqIHtAbGluayBJbnRlcmNlcHRvckNvbnRleHR9IEFGVEVSIGF1dG8tY29uZmlndXJhdGlvbiBjb21wdXRlcyB0aGUgZW52IGFuZCBCRUZPUkVcbiAqIEFwcEtpdCBib290cyAtIHNvIGFuIGludGVyY2VwdG9yIGNhbiByZWFkIHRoZSByZXNvbHZlZCBjb25uZWN0aW9uLCByZWdpc3RlclxuICogbGlmZWN5Y2xlIGhhbmRsZXJzLCBhbmQgc3RhcnQgYXV4aWxpYXJ5IHdvcmsuIEEgaGlkZGVuIHtAbGluayBsaWZlY3ljbGVCcmlkZ2V9XG4gKiBwbHVnaW4gaXMgaW5qZWN0ZWQgc28gdGhvc2UgYG9uTGlmZWN5Y2xlYCBoYW5kbGVycyBmaXJlIG9uIHRoZSBnZW51aW5lIEFwcEtpdFxuICogZXZlbnRzOyBpdCBoYXMgbm8gZXhwb3J0cywgc28gdGhlIHJldHVybmVkIHtAbGluayBQbHVnaW5NYXB9IGlzIHVuY2hhbmdlZC5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IHsgbGFrZWJhc2UsIHNlcnZlciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbiAqIGltcG9ydCB7IGFwcGtpdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuICpcbiAqIGNvbnN0IGFwcCA9IGF3YWl0IGFwcGtpdC5jcmVhdGVBcHAoeyBwbHVnaW5zOiBbc2VydmVyKCksIGxha2ViYXNlKCldIH0pO1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlQXBwPFQgZXh0ZW5kcyBBcHBLaXRQbHVnaW5zPihcbiAgY29uZmlnPzogQ3JlYXRlQXBwQ29uZmlnPFQ+LFxuKTogUHJvbWlzZTxQbHVnaW5NYXA8VD4+IHtcbiAgaW5zdGFsbEFzVXNlckRldmVsb3BtZW50UGF0Y2goKTtcbiAgYXdhaXQgY29uZmlndXJlTmF0aXZlSHR0cFRlbGVtZXRyeSh7IHNwYW5Ib29rOiBzdGFtcEh0dHBUcmFjZVVzZXIgfSk7XG4gIGNvbnN0IHBsdWdpbnMgPSBwbHVnaW5OYW1lcyhjb25maWcpO1xuICBjb25zdCBpbnRlcmNlcHRvcnMgPSBpbnRlcmNlcHRvckxpc3QoY29uZmlnPy5pbnRlcmNlcHRvcik7XG4gIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZUFwcDogc3RhcnRcIiwge1xuICAgIHBsdWdpbnMsXG4gICAgcGx1Z2luQ291bnQ6IHBsdWdpbnMubGVuZ3RoLFxuICAgIGludGVyY2VwdG9yQ291bnQ6IGludGVyY2VwdG9ycy5sZW5ndGgsXG4gICAgYXV0b0NvbmZpZ3VyZTogY29uZmlnPy5hdXRvQ29uZmlndXJlID8/IFwiKGRlZmF1bHQpXCIsXG4gICAgaGFzT25QbHVnaW5zUmVhZHk6IHR5cGVvZiBjb25maWc/Lm9uUGx1Z2luc1JlYWR5ID09PSBcImZ1bmN0aW9uXCIsXG4gIH0pO1xuXG4gIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZUFwcDogYXV0b0NvbmZpZ3VyZVwiKTtcbiAgY29uc3QgYnJhbmRDb250ZXh0ID0gYXdhaXQgbG9hZEJyYW5kQ29udGV4dCgpO1xuICBsb2dnZXIuZGVidWcoXCJjcmVhdGVBcHA6IGJyYW5kIGNvbnRleHQgbG9hZGVkXCIsIHsgbmFtZTogYnJhbmRDb250ZXh0Lm5hbWUgfSk7XG4gIGNvbnN0IGxha2ViYXNlID0gYXdhaXQgYXV0b0NvbmZpZ3VyZShjb25maWcpO1xuICBsb2dnZXIuZGVidWcoXCJjcmVhdGVBcHA6IGF1dG9Db25maWd1cmUgcmV0dXJuZWRcIiwge1xuICAgIGxha2ViYXNlOiBsYWtlYmFzZSA/IHJlZGFjdExha2ViYXNlQ29ubmVjdGlvbihsYWtlYmFzZSkgOiB1bmRlZmluZWQsXG4gIH0pO1xuXG4gIGNvbnN0IGFwcENvbmZpZyA9IHsgLi4uY29uZmlnIH07XG4gIGRlbGV0ZSBhcHBDb25maWcuYXV0b0NvbmZpZ3VyZTtcbiAgZGVsZXRlIGFwcENvbmZpZy5pbnRlcmNlcHRvcjtcbiAgY29uc3Qgb25QbHVnaW5zUmVhZHkgPSBhcHBDb25maWcub25QbHVnaW5zUmVhZHk7XG4gIGFwcENvbmZpZy5vblBsdWdpbnNSZWFkeSA9IGFzeW5jIChhcHApID0+IHtcbiAgICBjb25zdCBib3VuZCA9IGF3YWl0IGJpbmROYXRpdmVUZWxlbWV0cnlQcm92aWRlcigpO1xuICAgIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZUFwcDogbmF0aXZlIHRlbGVtZXRyeSBwcm92aWRlciBiaW5kaW5nXCIsIHsgYm91bmQgfSk7XG4gICAgYXdhaXQgb25QbHVnaW5zUmVhZHk/LihhcHApO1xuICB9O1xuXG4gIGlmIChzaG91bGRJbmplY3RDYWNoZVN0b3JhZ2UoY29uZmlnKSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZUFwcDogaW5qZWN0IG1lbW9yeS1maXJzdCBjYWNoZSBzdG9yYWdlXCIpO1xuICAgIGNvbnN0IHN0b3JhZ2UgPSBhd2FpdCBjcmVhdGVBcHBLaXRDYWNoZVN0b3JhZ2Uoe1xuICAgICAgY2FjaGU6IGNvbmZpZz8uY2FjaGUsXG4gICAgICBwcmVmZXJMYWtlYmFzZTogQm9vbGVhbihsYWtlYmFzZSkgfHwgdXNlc1BsdWdpbihjb25maWcsIExBS0VCQVNFX1BMVUdJTiksXG4gICAgfSk7XG4gICAgYXBwQ29uZmlnLmNhY2hlID0geyAuLi5jb25maWc/LmNhY2hlLCBzdG9yYWdlIH07XG4gICAgbG9nZ2VyLmRlYnVnKFwiY3JlYXRlQXBwOiBtZW1vcnktZmlyc3QgY2FjaGUgc3RvcmFnZSByZWFkeVwiLCB7XG4gICAgICBwZXJzaXN0ZW50OiBzdG9yYWdlLmlzUGVyc2lzdGVudCgpLFxuICAgIH0pO1xuICB9XG5cbiAgaWYgKGludGVyY2VwdG9ycy5sZW5ndGggPT09IDApIHtcbiAgICBsb2dnZXIuZGVidWcoXCJjcmVhdGVBcHA6IG5vIGludGVyY2VwdG9yczsgZGVsZWdhdGluZyB0byBBcHBLaXQgY3JlYXRlQXBwXCIsIHtcbiAgICAgIHBsdWdpbnM6IHBsdWdpbk5hbWVzKGFwcENvbmZpZyksXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYXBwa2l0Q3JlYXRlQXBwPFQ+KGFwcENvbmZpZyk7XG4gICAgbG9nZ2VyLmRlYnVnKFwiY3JlYXRlQXBwOiBBcHBLaXQgY3JlYXRlQXBwIHJldHVybmVkXCIsIHtcbiAgICAgIGV4cG9ydEtleXM6IE9iamVjdC5rZXlzKHJlc3VsdCA/PyB7fSksXG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8vIEJ1aWxkIHRoZSBjb250ZXh0IGZyb20gdGhlIGNvbXB1dGVkIGVudiwgcnVuIGVhY2ggaW50ZXJjZXB0b3IgKHRoZXkgcmVnaXN0ZXJcbiAgLy8gbGlmZWN5Y2xlIGhhbmRsZXJzICsgYmluZCBwcm9jZXNzZXMpLCB0aGVuIGluamVjdCB0aGUgYnJpZGdlIHRoYXQgcmVsYXlzIHRoZVxuICAvLyBSRUFMIEFwcEtpdCBsaWZlY3ljbGUgaW50byBgcnVudGltZS5lbWl0TGlmZWN5Y2xlYCBkdXJpbmcgaXRzIGBzZXR1cCgpYC5cbiAgY29uc3QgZW52ID0gcmVzb2x2ZWRBcHBFbnYobGFrZWJhc2UpO1xuICBsb2dnZXIuZGVidWcoXCJjcmVhdGVBcHA6IGludGVyY2VwdG9yIGNvbnRleHRcIiwge1xuICAgIGhhc0xha2ViYXNlOiBCb29sZWFuKGVudi5sYWtlYmFzZSksXG4gICAgZGF0YWJyaWNrc0hvc3Q6IGVudi5kYXRhYnJpY2tzSG9zdCxcbiAgICBpbnRlcmNlcHRvckNvdW50OiBpbnRlcmNlcHRvcnMubGVuZ3RoLFxuICB9KTtcbiAgY29uc3QgcnVudGltZTogSW50ZXJjZXB0b3JSdW50aW1lID0gY3JlYXRlSW50ZXJjZXB0b3JDb250ZXh0KGVudik7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaW50ZXJjZXB0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwiY3JlYXRlQXBwOiBydW4gaW50ZXJjZXB0b3JcIiwgeyBpbmRleDogaSwgb2Y6IGludGVyY2VwdG9ycy5sZW5ndGggfSk7XG4gICAgYXdhaXQgaW50ZXJjZXB0b3JzW2ldIShydW50aW1lLmNvbnRleHQpO1xuICAgIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZUFwcDogaW50ZXJjZXB0b3IgZG9uZVwiLCB7IGluZGV4OiBpIH0pO1xuICB9XG4gIC8vIEFwcGVuZCB0aGUgYnJpZGdlIHRvIHRoZSBwbHVnaW5zIHR1cGxlLiBJdCBpcyBoaWRkZW4gYW5kIGV4cG9ydHMgbm90aGluZywgc29cbiAgLy8gdGhlIHJldHVybmVkIG1hcCBzdGlsbCBtYXRjaGVzIGBQbHVnaW5NYXA8VD5gOyB0aGUgY2FzdCAodGhyb3VnaCBgdW5rbm93bmApIGlzXG4gIC8vIG9ubHkgYmVjYXVzZSBhcHBlbmRpbmcgd2lkZW5zIHRoZSB0dXBsZSB0eXBlIGJleW9uZCBgVGAuXG4gIGFwcENvbmZpZy5wbHVnaW5zID0gWy4uLihhcHBDb25maWcucGx1Z2lucyA/PyBbXSksIGxpZmVjeWNsZUJyaWRnZSh7IHJ1bnRpbWUgfSldIGFzIHVua25vd24gYXMgVDtcbiAgbG9nZ2VyLmRlYnVnKFwiY3JlYXRlQXBwOiBsaWZlY3ljbGUgYnJpZGdlIGluamVjdGVkOyBkZWxlZ2F0aW5nIHRvIEFwcEtpdCBjcmVhdGVBcHBcIiwge1xuICAgIHBsdWdpbnM6IHBsdWdpbk5hbWVzKGFwcENvbmZpZyksXG4gIH0pO1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCBhcHBraXRDcmVhdGVBcHA8VD4oYXBwQ29uZmlnKTtcbiAgbG9nZ2VyLmRlYnVnKFwiY3JlYXRlQXBwOiBBcHBLaXQgY3JlYXRlQXBwIHJldHVybmVkXCIsIHtcbiAgICBleHBvcnRLZXlzOiBPYmplY3Qua2V5cyhyZXN1bHQgPz8ge30pLFxuICB9KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBUaGUgQXBwS2l0IHBlci1yZXF1ZXN0IGV4ZWN1dGlvbiBjb250ZXh0IHJldHVybmVkIGJ5IGBnZXRFeGVjdXRpb25Db250ZXh0KClgXG4gKiAtIHRoZSBPQk8tc2NvcGVkIHdvcmtzcGFjZSBjbGllbnQgcGx1cyB0aGUgc3Vycm91bmRpbmcgcmVxdWVzdCBtZXRhZGF0YS5cbiAqIERlcml2ZWQgZnJvbSBBcHBLaXQncyBvd24gcmV0dXJuIHR5cGUgc28gaXQgdHJhY2tzIHRoZSBpbnN0YWxsZWQgdmVyc2lvbiwgYW5kXG4gKiByZS1leHBvcnRlZCBoZXJlIHNvIGFkZC1vbiBwYWNrYWdlcyBjYW4gdHlwZSBhIGNvbnRleHQgcGFyYW1ldGVyIHdpdGhvdXQgZWFjaFxuICogcmUtZGVyaXZpbmcgdGhlIHNhbWUgYFJldHVyblR5cGU8dHlwZW9mIGdldEV4ZWN1dGlvbkNvbnRleHQ+YCBpbmxpbmUuXG4gKi9cbmV4cG9ydCB0eXBlIEV4ZWN1dGlvbkNvbnRleHRMaWtlID0gUmV0dXJuVHlwZTx0eXBlb2YgZ2V0RXhlY3V0aW9uQ29udGV4dD47XG5cbi8qKlxuICogVGhlIGF1dGgtc2NvcGVkIERhdGFicmlja3Mgd29ya3NwYWNlIGNsaWVudCBjYXJyaWVkIG9uIGFuXG4gKiBgRXhlY3V0aW9uQ29udGV4dExpa2VgIChgZ2V0RXhlY3V0aW9uQ29udGV4dCgpLmNsaWVudGApLiBUeXBlZCBzdHJ1Y3R1cmFsbHlcbiAqIG9mZiBBcHBLaXQgc28gY29uc3VtZXJzIGRvbid0IHRha2UgYSBkaXJlY3QgYEBkYXRhYnJpY2tzL3Nkay1leHBlcmltZW50YWxgXG4gKiBkZXBlbmRlbmN5IC0gdGhlIGRlcCBmbG93cyBpbiB0cmFuc2l0aXZlbHkgdGhyb3VnaCBgQGRhdGFicmlja3MvYXBwa2l0YC5cbiAqL1xuZXhwb3J0IHR5cGUgV29ya3NwYWNlQ2xpZW50TGlrZSA9IEV4ZWN1dGlvbkNvbnRleHRMaWtlW1wiY2xpZW50XCJdO1xuXG4vKipcbiAqIFRoZSBjdXJyZW50IEFwcEtpdCBleGVjdXRpb24gY29udGV4dCwgb3IgYHVuZGVmaW5lZGAgd2hlbiBBcHBLaXQgaXNuJ3RcbiAqIGluaXRpYWxpemVkIChvdXRzaWRlIGEgcmVxdWVzdCBzY29wZSkuIFN3YWxsb3dzIEFwcEtpdCdzXG4gKiB7QGxpbmsgSW5pdGlhbGl6YXRpb25FcnJvcn07IGFueSBvdGhlciBlcnJvciBwcm9wYWdhdGVzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgeyBhcHBraXQgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbiAqIGltcG9ydCB7IGNyZWF0ZVdvcmtzcGFjZUNsaWVudCB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbiAqXG4gKiAvLyBPQk8tc2NvcGVkIGluc2lkZSBhIHJlcXVlc3QsIHNlcnZpY2UgcHJpbmNpcGFsIGZyb20gYSBDTEkgb3Igc2NyaXB0LlxuICogY29uc3QgY2xpZW50ID0gYXBwa2l0LnRyeUdldEV4ZWN1dGlvbkNvbnRleHQoKT8uY2xpZW50ID8/IGNyZWF0ZVdvcmtzcGFjZUNsaWVudCgpO1xuICovXG5leHBvcnQgZnVuY3Rpb24gdHJ5R2V0RXhlY3V0aW9uQ29udGV4dCgpOiBFeGVjdXRpb25Db250ZXh0TGlrZSB8IHVuZGVmaW5lZCB7XG4gIHRyeSB7XG4gICAgY29uc3QgY3R4ID0gZ2V0RXhlY3V0aW9uQ29udGV4dCgpO1xuICAgIGlmIChjdHg/LmNsaWVudCkge1xuICAgICAgcmV0dXJuIGN0eDtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKCEoZXJyb3IgaW5zdGFuY2VvZiBJbml0aWFsaXphdGlvbkVycm9yKSkge1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZSBhIGJhcmUgQXBwS2l0IGFwcCAobm8gcGx1Z2lucykgd2hlbiBub25lIGlzIHJ1bm5pbmcgeWV0LlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgeyBhcHBraXQgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbiAqXG4gKiBhd2FpdCBhcHBraXQuZW5zdXJlSW5pdGlhbGl6ZWQoKTtcbiAqIGNvbnN0IGNsaWVudCA9IGFwcGtpdC50cnlHZXRFeGVjdXRpb25Db250ZXh0KCk/LmNsaWVudDtcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGVuc3VyZUluaXRpYWxpemVkKCk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAodHJ5R2V0RXhlY3V0aW9uQ29udGV4dCgpKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwiZW5zdXJlSW5pdGlhbGl6ZWQ6IGFscmVhZHkgaW5pdGlhbGl6ZWRcIik7XG4gICAgcmV0dXJuO1xuICB9XG4gIGxvZ2dlci5kZWJ1ZyhcImVuc3VyZUluaXRpYWxpemVkOiBib290aW5nIGJhcmUgQXBwS2l0IGFwcFwiKTtcbiAgYXdhaXQgY3JlYXRlQXBwKHsgcGx1Z2luczogW10sIGF1dG9Db25maWd1cmU6IGZhbHNlIH0pO1xuICBsb2dnZXIuZGVidWcoXCJlbnN1cmVJbml0aWFsaXplZDogYmFyZSBBcHBLaXQgaW5pdGlhbGl6YXRpb24gY29tcGxldGVcIik7XG59XG4iXX0=
346
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwa2l0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwcGtpdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMkJHO0FBRUgsT0FBTyxFQUNMLFNBQVMsSUFBSSxlQUFlLEVBQzVCLG1CQUFtQixFQUNuQixtQkFBbUIsR0FDcEIsTUFBTSxvQkFBb0IsQ0FBQztBQUk1QixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDakQsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDM0UsT0FBTyxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU3RCxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN0RCxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDakQsT0FBTyxFQUFFLDZCQUE2QixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzlELE9BQU8sRUFDTCx3QkFBd0IsRUFHeEIsZUFBZSxHQUVoQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBMkIsTUFBTSx3QkFBd0IsQ0FBQztBQUNuRixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0RCxPQUFPLEVBQ0wsMkJBQTJCLEVBQzNCLDRCQUE0QixFQUM1QixrQkFBa0IsR0FDbkIsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBc0RwQyxNQUFNLGVBQWUsR0FBRyxVQUFVLENBQUM7QUFFbkM7Ozs7OztHQU1HO0FBQ0gsTUFBTSx5QkFBeUIsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFDO0FBRTlDLFNBQVMsVUFBVSxDQUNqQixNQUFzQyxFQUN0QyxJQUFZO0lBRVosT0FBTyxPQUFPLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQztBQUN4RSxDQUFDO0FBRUQsb0RBQW9EO0FBQ3BELFNBQVMsV0FBVyxDQUFDLE1BQW1DO0lBQ3RELE9BQU8sQ0FBQyxNQUFNLEVBQUUsT0FBTyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzVELENBQUM7QUFFRCxxRUFBcUU7QUFDckUsTUFBTSxVQUFVLG1CQUFtQixDQUNqQyxJQUFrQyxFQUNsQyxlQUFlLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRO0lBRXRDLElBQUksSUFBSSxLQUFLLElBQUk7UUFBRSxPQUFPLElBQUksQ0FBQztJQUMvQixJQUFJLElBQUksS0FBSyxLQUFLO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDakMsT0FBTyxlQUFlLEtBQUssYUFBYSxDQUFDO0FBQzNDLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxhQUFhLENBQ2pDLE1BQTJCLEVBQzNCLE1BQW9CO0lBRXBCLE1BQU0sYUFBYSxHQUFHLG1CQUFtQixFQUFFLENBQUM7SUFDNUMsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3BDLE1BQU0sTUFBTSxHQUFHLDBCQUEwQixDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDMUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsRUFBRTtRQUNuQyxHQUFHLE1BQU07UUFDVCxPQUFPO1FBQ1AsU0FBUyxFQUFFLHlCQUF5QjtRQUNwQyxZQUFZLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQztLQUM5QixDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzFCLE1BQU0sQ0FBQyxLQUFLLENBQUMscUJBQXFCLEVBQUUsRUFBRSxHQUFHLE1BQU0sRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzVELE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ25CLGFBQWEsRUFBRSxNQUFNLENBQUMsSUFBSTtZQUMxQixxQkFBcUIsRUFBRSxNQUFNLENBQUMscUJBQXFCO1lBQ25ELHFCQUFxQixFQUFFLE1BQU0sQ0FBQyxxQkFBcUI7WUFDbkQsV0FBVyxFQUFFLEtBQUs7WUFDbEIsYUFBYSxFQUFFLE1BQU0sQ0FBQyxhQUFhO1NBQ3BDLENBQUMsQ0FBQztRQUNILE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO0lBQ3pDLGNBQWMsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDbkMsY0FBYyxDQUFDLFVBQVUsRUFBRSxXQUFXLENBQUMsT0FBTyxDQUFDLHlCQUF5QixDQUFDLENBQUMsQ0FBQztJQUUzRSxNQUFNLENBQUMsS0FBSyxDQUFDLGlDQUFpQyxFQUFFO1FBQzlDLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUztRQUMzQixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7S0FDbEIsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxRQUFRLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLFVBQVUsQ0FBQyxNQUFNLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDakcsTUFBTSxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsRUFBRTtRQUNsQyxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7UUFDakIscUJBQXFCLEVBQUUsTUFBTSxDQUFDLHFCQUFxQjtRQUNuRCxxQkFBcUIsRUFBRSxNQUFNLENBQUMscUJBQXFCO1FBQ25ELFdBQVcsRUFBRSxNQUFNLENBQUMsU0FBUztRQUM3QixHQUFHLHdCQUF3QixDQUFDLFFBQVEsQ0FBQztLQUN0QyxDQUFDLENBQUM7SUFDSCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtRQUNuQixhQUFhLEVBQUUsTUFBTSxDQUFDLElBQUk7UUFDMUIscUJBQXFCLEVBQUUsTUFBTSxDQUFDLHFCQUFxQjtRQUNuRCxxQkFBcUIsRUFBRSxNQUFNLENBQUMscUJBQXFCO1FBQ25ELFdBQVcsRUFBRSxNQUFNLENBQUMsU0FBUztLQUM5QixDQUFDLENBQUM7SUFDSCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxLQUFLLFVBQVUscUJBQXFCLENBQ2xDLFNBQWtCLEVBQ2xCLE1BQW1CLEVBQ25CLGFBQXNCO0lBRXRCLE1BQU0sQ0FBQyxLQUFLLENBQUMseUNBQXlDLENBQUMsQ0FBQztJQUN4RCxNQUFNLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsRUFBRSxhQUFhLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM3RSxNQUFNLENBQUMsS0FBSyxDQUFDLG9DQUFvQyxFQUFFO1FBQ2pELEdBQUcsd0JBQXdCLENBQUMsUUFBUSxDQUFDO1FBQ3JDLElBQUk7UUFDSixHQUFHLEVBQUU7WUFDSCxpQkFBaUIsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQjtZQUNoRCxNQUFNLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNO1lBQzFCLE1BQU0sRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU07WUFDMUIsVUFBVSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVTtZQUNsQyxNQUFNLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNO1lBQzFCLFNBQVMsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVM7U0FDakM7S0FDRixDQUFDLENBQUM7SUFDSCxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxFQUFFLEdBQUcsd0JBQXdCLENBQUMsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUM1RSxJQUFJLFNBQVMsRUFBRSxDQUFDO1FBQ2QsTUFBTSxDQUFDLEtBQUssQ0FBQyw2Q0FBNkMsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDdEUsTUFBTSxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDekMsTUFBTSxDQUFDLEtBQUssQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO0lBQ25FLENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSxDQUFDLEtBQUssQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDO0FBRUQsU0FBUyxtQkFBbUI7SUFDMUIsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUNqRSxNQUFNLFFBQVEsR0FBRyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDM0UsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2QsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLHlCQUF5QixDQUFDO1FBQzdDLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLHlCQUF5QixHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDdEQsT0FBTyxRQUFRLENBQUMsSUFBSSxDQUFDO0FBQ3ZCLENBQUM7QUFFRCxnRkFBZ0Y7QUFDaEYsU0FBUyx3QkFBd0IsQ0FBQyxNQUFtQztJQUNuRSxNQUFNLEtBQUssR0FBRyxNQUFNLEVBQUUsS0FBSyxDQUFDO0lBQzVCLElBQUksS0FBSyxFQUFFLE9BQU8sS0FBSyxLQUFLO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDM0MsSUFBSSxLQUFLLEVBQUUsT0FBTztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ2pDLE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUVELFNBQVMsd0JBQXdCLENBQUMsUUFBNEI7SUFDNUQsT0FBTztRQUNMLE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTztRQUN6QixNQUFNLEVBQUUsUUFBUSxDQUFDLE1BQU07UUFDdkIsUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRO1FBQzNCLFFBQVEsRUFBRSxRQUFRLENBQUMsUUFBUTtRQUMzQixJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUk7UUFDbkIsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJO1FBQ25CLE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTztLQUMxQixDQUFDO0FBQ0osQ0FBQztBQUVELHVGQUF1RjtBQUN2RixTQUFTLGNBQWMsQ0FBQyxRQUF3QztJQUM5RCxPQUFPO1FBQ0wsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ2pDLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsRUFBRSxjQUFjLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQ3hGLENBQUM7QUFDSixDQUFDO0FBRUQsb0ZBQW9GO0FBQ3BGLFNBQVMsZUFBZSxDQUFDLFdBQTJDO0lBQ2xFLElBQUksQ0FBQyxXQUFXO1FBQUUsT0FBTyxFQUFFLENBQUM7SUFDNUIsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUM7QUFDbEUsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxTQUFTLENBQzdCLE1BQTJCO0lBRTNCLDZCQUE2QixFQUFFLENBQUM7SUFDaEMsTUFBTSw0QkFBNEIsQ0FBQyxFQUFFLFFBQVEsRUFBRSxrQkFBa0IsRUFBRSxDQUFDLENBQUM7SUFDckUsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3BDLE1BQU0sWUFBWSxHQUFHLGVBQWUsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDMUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsRUFBRTtRQUMvQixPQUFPO1FBQ1AsV0FBVyxFQUFFLE9BQU8sQ0FBQyxNQUFNO1FBQzNCLGdCQUFnQixFQUFFLFlBQVksQ0FBQyxNQUFNO1FBQ3JDLGFBQWEsRUFBRSxNQUFNLEVBQUUsYUFBYSxJQUFJLFdBQVc7UUFDbkQsaUJBQWlCLEVBQUUsT0FBTyxNQUFNLEVBQUUsY0FBYyxLQUFLLFVBQVU7S0FDaEUsQ0FBQyxDQUFDO0lBRUgsTUFBTSxDQUFDLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sWUFBWSxHQUFHLE1BQU0sZ0JBQWdCLEVBQUUsQ0FBQztJQUM5QyxNQUFNLENBQUMsS0FBSyxDQUFDLGlDQUFpQyxFQUFFLEVBQUUsSUFBSSxFQUFFLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzdFLE1BQU0sUUFBUSxHQUFHLE1BQU0sYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzdDLE1BQU0sQ0FBQyxLQUFLLENBQUMsbUNBQW1DLEVBQUU7UUFDaEQsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsd0JBQXdCLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVM7S0FDcEUsQ0FBQyxDQUFDO0lBRUgsTUFBTSxTQUFTLEdBQUcsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO0lBQ2hDLE9BQU8sU0FBUyxDQUFDLGFBQWEsQ0FBQztJQUMvQixPQUFPLFNBQVMsQ0FBQyxLQUFLLENBQUM7SUFDdkIsT0FBTyxTQUFTLENBQUMsV0FBVyxDQUFDO0lBQzdCLE1BQU0sY0FBYyxHQUFHLFNBQVMsQ0FBQyxjQUFjLENBQUM7SUFDaEQsU0FBUyxDQUFDLGNBQWMsR0FBRyxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUU7UUFDdkMsTUFBTSxLQUFLLEdBQUcsTUFBTSwyQkFBMkIsRUFBRSxDQUFDO1FBQ2xELE1BQU0sQ0FBQyxLQUFLLENBQUMsOENBQThDLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3hFLE1BQU0sY0FBYyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDOUIsQ0FBQyxDQUFDO0lBRUYsSUFBSSx3QkFBd0IsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ3JDLE1BQU0sQ0FBQyxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztRQUM3RCxNQUFNLE9BQU8sR0FBRyxNQUFNLHdCQUF3QixDQUFDO1lBQzdDLEtBQUssRUFBRSxNQUFNLEVBQUUsS0FBSztZQUNwQixjQUFjLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxNQUFNLEVBQUUsZUFBZSxDQUFDO1NBQ3pFLENBQUMsQ0FBQztRQUNILFNBQVMsQ0FBQyxLQUFLLEdBQUcsRUFBRSxHQUFHLE1BQU0sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDaEQsTUFBTSxDQUFDLEtBQUssQ0FBQyw2Q0FBNkMsRUFBRTtZQUMxRCxVQUFVLEVBQUUsT0FBTyxDQUFDLFlBQVksRUFBRTtTQUNuQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsSUFBSSxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLHlCQUF5QixDQUFDLEVBQUUsQ0FBQztRQUN6RixTQUFTLENBQUMsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLEVBQUUsWUFBWSxFQUFFLENBQWlCLENBQUM7UUFDbkYsTUFBTSxDQUFDLEtBQUssQ0FBQywyQ0FBMkMsRUFBRTtZQUN4RCxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssSUFBSSxNQUFNO1lBQzdCLGVBQWUsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVE7U0FDdEMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELElBQUksWUFBWSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUM5QixNQUFNLENBQUMsS0FBSyxDQUFDLDREQUE0RCxFQUFFO1lBQ3pFLE9BQU8sRUFBRSxXQUFXLENBQUMsU0FBUyxDQUFDO1NBQ2hDLENBQUMsQ0FBQztRQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sZUFBZSxDQUFJLFNBQVMsQ0FBQyxDQUFDO1FBQ25ELE1BQU0sQ0FBQyxLQUFLLENBQUMsc0NBQXNDLEVBQUU7WUFDbkQsVUFBVSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQztTQUN0QyxDQUFDLENBQUM7UUFDSCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQsK0VBQStFO0lBQy9FLCtFQUErRTtJQUMvRSwyRUFBMkU7SUFDM0UsTUFBTSxHQUFHLEdBQUcsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3JDLE1BQU0sQ0FBQyxLQUFLLENBQUMsZ0NBQWdDLEVBQUU7UUFDN0MsV0FBVyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO1FBQ2xDLGNBQWMsRUFBRSxHQUFHLENBQUMsY0FBYztRQUNsQyxnQkFBZ0IsRUFBRSxZQUFZLENBQUMsTUFBTTtLQUN0QyxDQUFDLENBQUM7SUFDSCxNQUFNLE9BQU8sR0FBdUIsd0JBQXdCLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbEUsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUM3QyxNQUFNLENBQUMsS0FBSyxDQUFDLDRCQUE0QixFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDbEYsTUFBTSxZQUFZLENBQUMsQ0FBQyxDQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sQ0FBQyxLQUFLLENBQUMsNkJBQTZCLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBQ0QsK0VBQStFO0lBQy9FLGlGQUFpRjtJQUNqRiwyREFBMkQ7SUFDM0QsU0FBUyxDQUFDLE9BQU8sR0FBRyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQyxFQUFFLGVBQWUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQWlCLENBQUM7SUFDakcsTUFBTSxDQUFDLEtBQUssQ0FBQyxzRUFBc0UsRUFBRTtRQUNuRixPQUFPLEVBQUUsV0FBVyxDQUFDLFNBQVMsQ0FBQztLQUNoQyxDQUFDLENBQUM7SUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLGVBQWUsQ0FBSSxTQUFTLENBQUMsQ0FBQztJQUNuRCxNQUFNLENBQUMsS0FBSyxDQUFDLHNDQUFzQyxFQUFFO1FBQ25ELFVBQVUsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUM7S0FDdEMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQW1CRDs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQU0sVUFBVSxzQkFBc0I7SUFDcEMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxHQUFHLEdBQUcsbUJBQW1CLEVBQUUsQ0FBQztRQUNsQyxJQUFJLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQztZQUNoQixPQUFPLEdBQUcsQ0FBQztRQUNiLENBQUM7SUFDSCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLElBQUksQ0FBQyxDQUFDLEtBQUssWUFBWSxtQkFBbUIsQ0FBQyxFQUFFLENBQUM7WUFDNUMsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sU0FBUyxDQUFDO0FBQ25CLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsaUJBQWlCO0lBQ3JDLElBQUksc0JBQXNCLEVBQUUsRUFBRSxDQUFDO1FBQzdCLE1BQU0sQ0FBQyxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQztRQUN2RCxPQUFPO0lBQ1QsQ0FBQztJQUNELE1BQU0sQ0FBQyxLQUFLLENBQUMsNENBQTRDLENBQUMsQ0FBQztJQUMzRCxNQUFNLFNBQVMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDdkQsTUFBTSxDQUFDLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO0FBQ3pFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEFwcEtpdCBydW50aW1lIGdsdWU6IHRoZSBhdXRvLWNvbmZpZ3VyaW5nIGBjcmVhdGVBcHBgIGRyb3AtaW4sIHBsdXMgdGhlXG4gKiBwZXItcmVxdWVzdCBleGVjdXRpb24gY29udGV4dCBoZWxwZXJzIGFuZCB0eXBlcyBkZXJpdmVkIGZyb20gaXQuXG4gKlxuICogYGNyZWF0ZUFwcGAgcnVucyBkYngtdG9vbHMgYXV0by1jb25maWd1cmF0aW9uLCB0aGVuIGRlbGVnYXRlcyB0byBBcHBLaXQncyBvd25cbiAqIGBjcmVhdGVBcHBgIHdpdGggdGhlIHNhbWUgYXJndW1lbnRzIGFuZCB0aGUgc2FtZSB0eXBlZCBwbHVnaW4tZXhwb3J0IG1hcC5cbiAqIERyb3AgaXQgaW4gYXMgYSBvbmUtZm9yLW9uZSByZXBsYWNlbWVudDpcbiAqXG4gKiBgYGB0c1xuICogaW1wb3J0IHsgbGFrZWJhc2UsIHNlcnZlciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbiAqIGltcG9ydCB7IGFwcGtpdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuICpcbiAqIGF3YWl0IGFwcGtpdC5jcmVhdGVBcHAoeyBwbHVnaW5zOiBbc2VydmVyKCksIGxha2ViYXNlKCldIH0pO1xuICogYGBgXG4gKlxuICogQXV0by1jb25maWd1cmF0aW9uIHJ1bnMgQkVGT1JFIGRlbGVnYXRpbmcgc28gcGx1Z2lucyBzZWUgYSBmdWxseSBwb3B1bGF0ZWRcbiAqIGBwcm9jZXNzLmVudmAgZHVyaW5nIHRoZWlyIHN5bmNocm9ub3VzIGBzZXR1cCgpYC4gTGFrZWJhc2UgUG9zdGdyZXMgcmVzb2x1dGlvblxuICogcnVucyB3aGVuIGEgbmF0aXZlIGBsYWtlYmFzZWAgb3IgYGRhdGFiYXNlYCBwbHVnaW4gaXMgcHJlc2VudCwgb3Igd2hlblxuICoge0BsaW5rIEF1dG9Db25maWd1cmVNb2RlfSBpcyBzZXQgZXhwbGljaXRseSBvbiB0aGUgY29uZmlnIG9iamVjdC5cbiAqXG4gKiBgZ2V0RXhlY3V0aW9uQ29udGV4dCgpYCBpcyBBcHBLaXQncyBvd24gYWNjZXNzb3IgZm9yIHRoZSBPQk8tc2NvcGVkIHdvcmtzcGFjZVxuICogY2xpZW50ICsgcmVxdWVzdCBtZXRhZGF0YTsgdGhlIHdyYXBwZXJzIGhlcmUgbWFrZSBpdCBzYWZlIHRvIGNhbGwgb3V0c2lkZSBhXG4gKiByZXF1ZXN0IHNjb3BlICh7QGxpbmsgdHJ5R2V0RXhlY3V0aW9uQ29udGV4dH0pIGFuZCB0byBsYXppbHkgYm9vdCBhIGJhcmUgYXBwXG4gKiAoe0BsaW5rIGVuc3VyZUluaXRpYWxpemVkfSksIGFuZCByZS1leHBvcnQgdGhlIGRlcml2ZWQgdHlwZXMgc28gYWRkLW9uXG4gKiBwYWNrYWdlcyBjYW4gdHlwZSBhIGNvbnRleHQgLyBjbGllbnQgd2l0aG91dCByZS1kZXJpdmluZyB0aGVtIGlubGluZS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHtcbiAgY3JlYXRlQXBwIGFzIGFwcGtpdENyZWF0ZUFwcCxcbiAgZ2V0RXhlY3V0aW9uQ29udGV4dCxcbiAgSW5pdGlhbGl6YXRpb25FcnJvcixcbn0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuLy8gQXBwS2l0J3Mgcm9vdCBiYXJyZWwgcmUtZXhwb3J0cyBgUGx1Z2luRGF0YWAgYnV0IG5vdCBgUGx1Z2luTWFwYDsgdGhlIHBhY2thZ2Vcbi8vIHB1Ymxpc2hlcyB0aGlzIHN1YnBhdGggZm9yIGV4YWN0bHkgdGhhdCB0eXBlLlxuaW1wb3J0IHR5cGUgeyBQbHVnaW5NYXAgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0L2Rpc3Qvc2hhcmVkL3NyYy9wbHVnaW5cIjtcbmltcG9ydCB7IHJlc29sdmVQcm9maWxlIH0gZnJvbSBcIkBkYngtdG9vbHMvYXV0aFwiO1xuaW1wb3J0IHsgREVCVUdfQ0FQVFVSRV9QTFVHSU5fTkFNRSB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1hcHBraXQvZGVidWdcIjtcbmltcG9ydCB7IGxvZywgdGllQWJvcnRTaWduYWwgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuXG5pbXBvcnQgeyByZXNvbHZlQXV0b0NvbmZpZ3VyZVBvbGljeSB9IGZyb20gXCIuL19hdXRvLWNvbmZpZ3VyZS50c1wiO1xuaW1wb3J0IHsgbG9hZEJyYW5kQ29udGV4dCB9IGZyb20gXCIuL2JyYW5kLWNvbnRleHQudHNcIjtcbmltcG9ydCB7IGNyZWF0ZUFwcEtpdENhY2hlU3RvcmFnZSB9IGZyb20gXCIuL2NhY2hlLXN0b3JhZ2UudHNcIjtcbmltcG9ydCB7IGRlYnVnQ2FwdHVyZSB9IGZyb20gXCIuL2RlYnVnL3BsdWdpbi50c1wiO1xuaW1wb3J0IHsgaW5zdGFsbEFzVXNlckRldmVsb3BtZW50UGF0Y2ggfSBmcm9tIFwiLi9pZGVudGl0eS50c1wiO1xuaW1wb3J0IHtcbiAgY3JlYXRlSW50ZXJjZXB0b3JDb250ZXh0LFxuICB0eXBlIEludGVyY2VwdG9yLFxuICB0eXBlIEludGVyY2VwdG9yUnVudGltZSxcbiAgbGlmZWN5Y2xlQnJpZGdlLFxuICB0eXBlIFJlc29sdmVkQXBwRW52LFxufSBmcm9tIFwiLi9pbnRlcmNlcHRvci50c1wiO1xuaW1wb3J0IHsgYXBwbHlMYWtlYmFzZUVudiwgdHlwZSBMYWtlYmFzZUNvbm5lY3Rpb24gfSBmcm9tIFwiLi9sYWtlYmFzZS1yZXNvbHZlci50c1wiO1xuaW1wb3J0IHsgcHJvdmlzaW9uQ2FjaGVTY2hlbWEgfSBmcm9tIFwiLi9wcm92aXNpb24udHNcIjtcbmltcG9ydCB7XG4gIGJpbmROYXRpdmVUZWxlbWV0cnlQcm92aWRlcixcbiAgY29uZmlndXJlTmF0aXZlSHR0cFRlbGVtZXRyeSxcbiAgc3RhbXBIdHRwVHJhY2VVc2VyLFxufSBmcm9tIFwiLi90ZWxlbWV0cnkudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImFwcGtpdFwiKTtcblxudHlwZSBBcHBLaXRDcmVhdGVBcHBDb25maWcgPSBOb25OdWxsYWJsZTxQYXJhbWV0ZXJzPHR5cGVvZiBhcHBraXRDcmVhdGVBcHA+WzBdPjtcbnR5cGUgQXBwS2l0UGx1Z2lucyA9IE5vbk51bGxhYmxlPEFwcEtpdENyZWF0ZUFwcENvbmZpZ1tcInBsdWdpbnNcIl0+O1xuXG4vKipcbiAqIFdoYXQgYXV0by1jb25maWd1cmF0aW9uIGRvZXMgYmVmb3JlIEFwcEtpdCBib290cy5cbiAqXG4gKiAtIGBcInByb3Zpc2lvblwiYDogcmVzb2x2ZSB0aGUgTGFrZWJhc2UgY29ubmVjdGlvbiBpbnRvIGBwcm9jZXNzLmVudmAsIHRoZW5cbiAqICAgZ3JhbnQgdGhlIEFwcEtpdCBjYWNoZSBzY2hlbWEgdG8gdGhlIGNvbm5lY3Rpbmcgcm9sZS5cbiAqIC0gYFwiZW52XCJgOiByZXNvbHZlIHRoZSBMYWtlYmFzZSBjb25uZWN0aW9uIGludG8gYHByb2Nlc3MuZW52YCBvbmx5LlxuICpcbiAqIE9taXQgaXQgdG8gcmVzb2x2ZSBkYXRhYmFzZSBlbnZpcm9ubWVudCB3aGVuIGEgbmF0aXZlIGBsYWtlYmFzZWAgb3JcbiAqIGBkYXRhYmFzZWAgcGx1Z2luIGlzIHJlZ2lzdGVyZWQuIEltcGxpY2l0IGNhY2hlLXNjaGVtYSBncmFudHMgcmVtYWluIGdhdGVkIG9uXG4gKiBgbGFrZWJhc2VgOyBgZGF0YWJhc2VgIG93bnMgaXRzIG93biBwb29sIGFuZCBkb2VzIG5vdCBicm9hZGVuIGdyYW50cy4gU2V0IHRoZVxuICogbW9kZSBleHBsaWNpdGx5IHRvIHJ1biByZWdhcmRsZXNzIG9mIHRoZSBwbHVnaW4gbGlzdCwgb3IgcGFzcyBgZmFsc2VgIHRvIHNraXBcbiAqIGF1dG8tY29uZmlndXJhdGlvbiBlbnRpcmVseS5cbiAqXG4gKiBTZXQgaXQgRVhQTElDSVRMWSBvbiBhbiBhcHAgdGhhdCBoYXMgbm8gYGxha2ViYXNlKClgIHBsdWdpbiBidXQgc3RpbGwgd2FudHNcbiAqIEFwcEtpdCdzIFBFUlNJU1RFTlQgY2FjaGUuIEFwcEtpdCBwaWNrcyBMYWtlYmFzZSBmb3IgYENhY2hlTWFuYWdlcmAgb25seSB3aGVuXG4gKiBgY3JlYXRlTGFrZWJhc2VQb29sKClgIGNhbiBidWlsZCBhIHBvb2wsIGFuZCB0aGF0IHJlYWRzIGBMQUtFQkFTRV9FTkRQT0lOVGAgL1xuICogYFBHSE9TVGAgLyBgUEdEQVRBQkFTRWAgc3RyYWlnaHQgZnJvbSBgcHJvY2Vzcy5lbnZgIC0gc28gd2l0aG91dCB0aGlzIHN0ZXAgdGhlXG4gKiBjYWNoZSBzaWxlbnRseSBmYWxscyBiYWNrIHRvIGluLW1lbW9yeSwgYW5kIGFueXRoaW5nIGl0IGhvbGRzIChhIHNlc3Npb25cbiAqIHNpZ25pbmcga2V5LCBhIG9uZS10aW1lIGNvZGUpIGlzIGxvc3Qgb24gcmVzdGFydC4gYFwiZW52XCJgIGlzIHRoZSByaWdodCBtb2RlXG4gKiB0aGVyZTogdGhlIGFwcCBTUCBjYW5ub3QgZ3JhbnQgb24gdGhlIGNhY2hlIHNjaGVtYSBhbnl3YXkuXG4gKi9cbmV4cG9ydCB0eXBlIEF1dG9Db25maWd1cmVNb2RlID0gXCJlbnZcIiB8IFwicHJvdmlzaW9uXCI7XG5cbi8qKiBBdXRvbWF0aWMgYnJvd3NlciBkZWJ1Zy1jYXB0dXJlIHJlZ2lzdHJhdGlvbiBwb2xpY3kuICovXG5leHBvcnQgdHlwZSBEZWJ1Z0NhcHR1cmVNb2RlID0gXCJhdXRvXCIgfCBib29sZWFuO1xuXG4vKiogQXBwS2l0J3MgYGNyZWF0ZUFwcGAgY29uZmlnIHBsdXMgdGhlIGRieC10b29scyBhdXRvLWNvbmZpZ3VyYXRpb24gc3dpdGNoLiAqL1xuZXhwb3J0IHR5cGUgQ3JlYXRlQXBwQ29uZmlnPFQgZXh0ZW5kcyBBcHBLaXRQbHVnaW5zID0gQXBwS2l0UGx1Z2lucz4gPSBPbWl0PFxuICBBcHBLaXRDcmVhdGVBcHBDb25maWcsXG4gIFwicGx1Z2luc1wiIHwgXCJvblBsdWdpbnNSZWFkeVwiXG4+ICYge1xuICBwbHVnaW5zPzogVDtcbiAgb25QbHVnaW5zUmVhZHk/OiAoYXBwa2l0OiBQbHVnaW5NYXA8VD4pID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+O1xuICAvKiogQXV0by1jb25maWd1cmF0aW9uIHRvIHJ1biBiZWZvcmUgQXBwS2l0IGJvb3RzLiBEZWZhdWx0cyB0byBgXCJwcm92aXNpb25cImAuICovXG4gIGF1dG9Db25maWd1cmU/OiBBdXRvQ29uZmlndXJlTW9kZSB8IGZhbHNlO1xuICAvKipcbiAgICogUmVnaXN0ZXIgQXBwS2l0IGJyb3dzZXIgZGVidWctY2FwdHVyZSByb3V0ZXMuIGBcImF1dG9cImAgKHRoZSBkZWZhdWx0KVxuICAgKiBlbmFibGVzIHRoZW0gb25seSB3aGVuIGBOT0RFX0VOVmAgaXMgYFwiZGV2ZWxvcG1lbnRcImAuXG4gICAqL1xuICBkZWJ1Zz86IERlYnVnQ2FwdHVyZU1vZGU7XG4gIC8qKlxuICAgKiBPbmUgb3IgbWFueSB7QGxpbmsgSW50ZXJjZXB0b3J9cyBoYW5kZWQgYW4ge0BsaW5rIEludGVyY2VwdG9yQ29udGV4dH0gb25jZVxuICAgKiBhdXRvLWNvbmZpZ3VyYXRpb24gaGFzIGNvbXB1dGVkIHRoZSBlbnYuIEVhY2ggcmVjZWl2ZXMgdGhlIHJlc29sdmVkIGVudiwgYW5cbiAgICogQXBwS2l0IGxpZmVjeWNsZSBob29rLiBTZWUgYC4vaW50ZXJjZXB0b3JgLiBUaGUgdHVubmVsIGlzIHRoZSBwcmltYXJ5XG4gICAqIGNvbnN1bWVyLlxuICAgKi9cbiAgaW50ZXJjZXB0b3I/OiBJbnRlcmNlcHRvciB8IEludGVyY2VwdG9yW107XG59O1xuXG5jb25zdCBMQUtFQkFTRV9QTFVHSU4gPSBcImxha2ViYXNlXCI7XG5cbi8qKlxuICogVXBwZXIgYm91bmQgb24gYm9vdC10aW1lIGF1dG8tY29uZmlndXJhdGlvbi4gSXQgcnVucyBhcyB0aGUgc2VydmljZSBwcmluY2lwYWxcbiAqIGJlZm9yZSBhbnkgcGx1Z2luIGlzIGNvbnN0cnVjdGVkLCBzbyBpdCBzaXRzIG91dHNpZGUgQXBwS2l0J3MgaW50ZXJjZXB0b3JcbiAqIGNoYWluIGFuZCBpbmhlcml0cyBubyB0aW1lb3V0LCByZXRyeSwgb3IgdGVsZW1ldHJ5IGZyb20gaXQuIFRoZSBidWRnZXQgY292ZXJzXG4gKiB0aGUgcmVzb2x2ZXIncyBvd24gd29yc3QgY2FzZSAoY3JlYXRlIGEgcHJvamVjdCwgdGhlbiB3YWl0IGZvciBpdHMgZW5kcG9pbnQpXG4gKiBwbHVzIHRoZSBjYWNoZS1zY2hlbWEgZ3JhbnRzLlxuICovXG5jb25zdCBBVVRPX0NPTkZJR1VSRV9USU1FT1VUX01TID0gMTEgKiA2MF8wMDA7XG5cbmZ1bmN0aW9uIHVzZXNQbHVnaW48VCBleHRlbmRzIEFwcEtpdFBsdWdpbnM+KFxuICBjb25maWc6IENyZWF0ZUFwcENvbmZpZzxUPiB8IHVuZGVmaW5lZCxcbiAgbmFtZTogc3RyaW5nLFxuKTogYm9vbGVhbiB7XG4gIHJldHVybiBCb29sZWFuKGNvbmZpZz8ucGx1Z2lucz8uc29tZSgoZW50cnkpID0+IGVudHJ5Lm5hbWUgPT09IG5hbWUpKTtcbn1cblxuLyoqIFBsdWdpbiBuYW1lcyBmb3IgYm9vdCBsb2dzIChvcmRlciBwcmVzZXJ2ZWQpLiAqL1xuZnVuY3Rpb24gcGx1Z2luTmFtZXMoY29uZmlnOiBDcmVhdGVBcHBDb25maWcgfCB1bmRlZmluZWQpOiBzdHJpbmdbXSB7XG4gIHJldHVybiAoY29uZmlnPy5wbHVnaW5zID8/IFtdKS5tYXAoKGVudHJ5KSA9PiBlbnRyeS5uYW1lKTtcbn1cblxuLyoqIFJlc29sdmUgdGhlIGBjcmVhdGVBcHAuZGVidWdgIHBvbGljeSBmb3Igb25lIE5vZGUgZW52aXJvbm1lbnQuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWdDYXB0dXJlRW5hYmxlZChcbiAgbW9kZTogRGVidWdDYXB0dXJlTW9kZSB8IHVuZGVmaW5lZCxcbiAgbm9kZUVudmlyb25tZW50ID0gcHJvY2Vzcy5lbnYuTk9ERV9FTlYsXG4pOiBib29sZWFuIHtcbiAgaWYgKG1vZGUgPT09IHRydWUpIHJldHVybiB0cnVlO1xuICBpZiAobW9kZSA9PT0gZmFsc2UpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIG5vZGVFbnZpcm9ubWVudCA9PT0gXCJkZXZlbG9wbWVudFwiO1xufVxuXG4vKipcbiAqIFJ1biBlbmFibGVkIGF1dG8tY29uZmlndXJhdGlvbiBzdGVwcyB3aXRob3V0IGNhbGxpbmcgQXBwS2l0J3MgYGNyZWF0ZUFwcGAuXG4gKlxuICogTGFrZWJhc2UgUG9zdGdyZXMgcmVzb2x2ZXMgd2hlbiB7QGxpbmsgQ3JlYXRlQXBwQ29uZmlnLmF1dG9Db25maWd1cmV9IGlzIHNldFxuICogZXhwbGljaXRseSBvciBhIG5hdGl2ZSBgbGFrZWJhc2VgL2BkYXRhYmFzZWAgcGx1Z2luIGlzIGxpc3RlZCBpblxuICogYGNvbmZpZy5wbHVnaW5zYC4gYHNpZ25hbGAgY2FuY2VscyB0aGUgcmVzb2x1dGlvbjsgaXQgaXMgY29tYmluZWQgd2l0aCBhblxuICogaW50ZXJuYWwgYm9vdCB0aW1lb3V0IGVpdGhlciB3YXkuXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCB7IGFwcGtpdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuICpcbiAqIC8vIFBvcHVsYXRlIFBHSE9TVCAvIFBHREFUQUJBU0UgLyBMQUtFQkFTRV9FTkRQT0lOVCB3aXRob3V0IGJvb3RpbmcgQXBwS2l0LlxuICogYXdhaXQgYXBwa2l0LmF1dG9Db25maWd1cmUoeyBhdXRvQ29uZmlndXJlOiBcImVudlwiIH0pO1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXV0b0NvbmZpZ3VyZTxUIGV4dGVuZHMgQXBwS2l0UGx1Z2lucz4oXG4gIGNvbmZpZz86IENyZWF0ZUFwcENvbmZpZzxUPixcbiAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4pOiBQcm9taXNlPExha2ViYXNlQ29ubmVjdGlvbiB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCBidW5kbGVQcm9maWxlID0gYXBwbHlEZWZhdWx0UHJvZmlsZSgpO1xuICBjb25zdCBwbHVnaW5zID0gcGx1Z2luTmFtZXMoY29uZmlnKTtcbiAgY29uc3QgcG9saWN5ID0gcmVzb2x2ZUF1dG9Db25maWd1cmVQb2xpY3kocGx1Z2lucywgY29uZmlnPy5hdXRvQ29uZmlndXJlKTtcbiAgbG9nZ2VyLmRlYnVnKFwiYXV0b0NvbmZpZ3VyZTogc3RhcnRcIiwge1xuICAgIC4uLnBvbGljeSxcbiAgICBwbHVnaW5zLFxuICAgIHRpbWVvdXRNczogQVVUT19DT05GSUdVUkVfVElNRU9VVF9NUyxcbiAgICBjYWxsZXJTaWduYWw6IEJvb2xlYW4oc2lnbmFsKSxcbiAgfSk7XG5cbiAgaWYgKCFwb2xpY3kuc2hvdWxkUmVzb2x2ZSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcImF1dG9Db25maWd1cmU6IHNraXBcIiwgeyAuLi5wb2xpY3ksIHBsdWdpbnMgfSk7XG4gICAgbG9nZ2VyLmluZm8oXCJyZWFkeVwiLCB7XG4gICAgICBhdXRvQ29uZmlndXJlOiBwb2xpY3kubW9kZSxcbiAgICAgIGxha2ViYXNlUGx1Z2luUHJlc2VudDogcG9saWN5Lmxha2ViYXNlUGx1Z2luUHJlc2VudCxcbiAgICAgIGRhdGFiYXNlUGx1Z2luUHJlc2VudDogcG9saWN5LmRhdGFiYXNlUGx1Z2luUHJlc2VudCxcbiAgICAgIHByb3Zpc2lvbmVkOiBmYWxzZSxcbiAgICAgIHNraXBwZWRSZWFzb246IHBvbGljeS5za2lwcGVkUmVhc29uLFxuICAgIH0pO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICB0aWVBYm9ydFNpZ25hbChjb250cm9sbGVyLCBzaWduYWwpO1xuICB0aWVBYm9ydFNpZ25hbChjb250cm9sbGVyLCBBYm9ydFNpZ25hbC50aW1lb3V0KEFVVE9fQ09ORklHVVJFX1RJTUVPVVRfTVMpKTtcblxuICBsb2dnZXIuZGVidWcoXCJhdXRvQ29uZmlndXJlOiByZXNvbHZlIGxha2ViYXNlXCIsIHtcbiAgICBwcm92aXNpb246IHBvbGljeS5wcm92aXNpb24sXG4gICAgbW9kZTogcG9saWN5Lm1vZGUsXG4gIH0pO1xuICBjb25zdCByZXNvbHZlZCA9IGF3YWl0IGF1dG9Db25maWd1cmVMYWtlYmFzZShwb2xpY3kucHJvdmlzaW9uLCBjb250cm9sbGVyLnNpZ25hbCwgYnVuZGxlUHJvZmlsZSk7XG4gIGxvZ2dlci5kZWJ1ZyhcImF1dG9Db25maWd1cmU6IGRvbmVcIiwge1xuICAgIG1vZGU6IHBvbGljeS5tb2RlLFxuICAgIGxha2ViYXNlUGx1Z2luUHJlc2VudDogcG9saWN5Lmxha2ViYXNlUGx1Z2luUHJlc2VudCxcbiAgICBkYXRhYmFzZVBsdWdpblByZXNlbnQ6IHBvbGljeS5kYXRhYmFzZVBsdWdpblByZXNlbnQsXG4gICAgcHJvdmlzaW9uZWQ6IHBvbGljeS5wcm92aXNpb24sXG4gICAgLi4ucmVkYWN0TGFrZWJhc2VDb25uZWN0aW9uKHJlc29sdmVkKSxcbiAgfSk7XG4gIGxvZ2dlci5pbmZvKFwicmVhZHlcIiwge1xuICAgIGF1dG9Db25maWd1cmU6IHBvbGljeS5tb2RlLFxuICAgIGxha2ViYXNlUGx1Z2luUHJlc2VudDogcG9saWN5Lmxha2ViYXNlUGx1Z2luUHJlc2VudCxcbiAgICBkYXRhYmFzZVBsdWdpblByZXNlbnQ6IHBvbGljeS5kYXRhYmFzZVBsdWdpblByZXNlbnQsXG4gICAgcHJvdmlzaW9uZWQ6IHBvbGljeS5wcm92aXNpb24sXG4gIH0pO1xuICByZXR1cm4gcmVzb2x2ZWQ7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBMYWtlYmFzZSBQb3N0Z3JlcyBjb25uZWN0aW9uIGluZm8sIHdyaXRlIHRoZSByZXNvbHZlZCB2YWx1ZXMgdG9cbiAqIGBwcm9jZXNzLmVudmAsIGFuZCByZXR1cm4gdGhlIHJlY29yZC4gVXNlZCBieSB7QGxpbmsgYXV0b0NvbmZpZ3VyZX07IGNhbGxcbiAqIHtAbGluayBhcHBseUxha2ViYXNlRW52fSBkaXJlY3RseSB3aGVuIGZpbmVyIGNvbnRyb2wgaXMgbmVlZGVkIChhIGRpZmZlcmVudFxuICogYGF1dG9DcmVhdGVgIHBvbGljeSwgb3IgYSBjYWxsZXIgdGhhdCB3YW50cyB0aGUgZW52IHdpdGhvdXQgYm9vdGluZyBBcHBLaXQpLlxuICovXG5hc3luYyBmdW5jdGlvbiBhdXRvQ29uZmlndXJlTGFrZWJhc2UoXG4gIHByb3Zpc2lvbjogYm9vbGVhbixcbiAgc2lnbmFsOiBBYm9ydFNpZ25hbCxcbiAgYnVuZGxlUHJvZmlsZT86IHN0cmluZyxcbik6IFByb21pc2U8TGFrZWJhc2VDb25uZWN0aW9uPiB7XG4gIGxvZ2dlci5kZWJ1ZyhcImF1dG9Db25maWd1cmVMYWtlYmFzZTogYXBwbHlMYWtlYmFzZUVudlwiKTtcbiAgY29uc3QgeyByZXNvbHZlZCwgdXNlciB9ID0gYXdhaXQgYXBwbHlMYWtlYmFzZUVudih7IGJ1bmRsZVByb2ZpbGUgfSwgc2lnbmFsKTtcbiAgbG9nZ2VyLmRlYnVnKFwiYXV0b0NvbmZpZ3VyZUxha2ViYXNlOiBlbnYgYXBwbGllZFwiLCB7XG4gICAgLi4ucmVkYWN0TGFrZWJhc2VDb25uZWN0aW9uKHJlc29sdmVkKSxcbiAgICB1c2VyLFxuICAgIGVudjoge1xuICAgICAgTEFLRUJBU0VfRU5EUE9JTlQ6IHByb2Nlc3MuZW52LkxBS0VCQVNFX0VORFBPSU5ULFxuICAgICAgUEdIT1NUOiBwcm9jZXNzLmVudi5QR0hPU1QsXG4gICAgICBQR1BPUlQ6IHByb2Nlc3MuZW52LlBHUE9SVCxcbiAgICAgIFBHREFUQUJBU0U6IHByb2Nlc3MuZW52LlBHREFUQUJBU0UsXG4gICAgICBQR1VTRVI6IHByb2Nlc3MuZW52LlBHVVNFUixcbiAgICAgIFBHU1NMTU9ERTogcHJvY2Vzcy5lbnYuUEdTU0xNT0RFLFxuICAgIH0sXG4gIH0pO1xuICBsb2dnZXIuaW5mbyhcImVudiB1cGRhdGVkXCIsIHsgLi4ucmVkYWN0TGFrZWJhc2VDb25uZWN0aW9uKHJlc29sdmVkKSwgdXNlciB9KTtcbiAgaWYgKHByb3Zpc2lvbikge1xuICAgIGxvZ2dlci5kZWJ1ZyhcImF1dG9Db25maWd1cmVMYWtlYmFzZTogcHJvdmlzaW9uQ2FjaGVTY2hlbWFcIiwgeyB1c2VyIH0pO1xuICAgIGF3YWl0IHByb3Zpc2lvbkNhY2hlU2NoZW1hKHVzZXIsIGxvZ2dlcik7XG4gICAgbG9nZ2VyLmRlYnVnKFwiYXV0b0NvbmZpZ3VyZUxha2ViYXNlOiBwcm92aXNpb25DYWNoZVNjaGVtYSBkb25lXCIpO1xuICB9IGVsc2Uge1xuICAgIGxvZ2dlci5kZWJ1ZyhcImF1dG9Db25maWd1cmVMYWtlYmFzZTogc2tpcCBwcm92aXNpb24gKG1vZGU9ZW52KVwiKTtcbiAgfVxuICByZXR1cm4gcmVzb2x2ZWQ7XG59XG5cbmZ1bmN0aW9uIGFwcGx5RGVmYXVsdFByb2ZpbGUoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgY29uZmlndXJlZCA9IHByb2Nlc3MuZW52LkRBVEFCUklDS1NfQ09ORklHX1BST0ZJTEU/LnRyaW0oKTtcbiAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlUHJvZmlsZShjb25maWd1cmVkID8geyBwcm9maWxlOiBjb25maWd1cmVkIH0gOiB7fSk7XG4gIGlmICghcmVzb2x2ZWQpIHtcbiAgICBkZWxldGUgcHJvY2Vzcy5lbnYuREFUQUJSSUNLU19DT05GSUdfUFJPRklMRTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIHByb2Nlc3MuZW52LkRBVEFCUklDS1NfQ09ORklHX1BST0ZJTEUgPSByZXNvbHZlZC5uYW1lO1xuICByZXR1cm4gcmVzb2x2ZWQubmFtZTtcbn1cblxuLyoqIFdoZXRoZXIgYGNyZWF0ZUFwcGAgc2hvdWxkIGluamVjdCB0aGUgZGVmYXVsdCBtZW1vcnktZmlyc3QgY2FjaGUgc3RvcmFnZS4gKi9cbmZ1bmN0aW9uIHNob3VsZEluamVjdENhY2hlU3RvcmFnZShjb25maWc6IENyZWF0ZUFwcENvbmZpZyB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICBjb25zdCBjYWNoZSA9IGNvbmZpZz8uY2FjaGU7XG4gIGlmIChjYWNoZT8uZW5hYmxlZCA9PT0gZmFsc2UpIHJldHVybiBmYWxzZTtcbiAgaWYgKGNhY2hlPy5zdG9yYWdlKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiByZWRhY3RMYWtlYmFzZUNvbm5lY3Rpb24ocmVzb2x2ZWQ6IExha2ViYXNlQ29ubmVjdGlvbik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgcmV0dXJuIHtcbiAgICBwcm9qZWN0OiByZXNvbHZlZC5wcm9qZWN0LFxuICAgIGJyYW5jaDogcmVzb2x2ZWQuYnJhbmNoLFxuICAgIGVuZHBvaW50OiByZXNvbHZlZC5lbmRwb2ludCxcbiAgICBkYXRhYmFzZTogcmVzb2x2ZWQuZGF0YWJhc2UsXG4gICAgaG9zdDogcmVzb2x2ZWQuaG9zdCxcbiAgICBwb3J0OiByZXNvbHZlZC5wb3J0LFxuICAgIHNzbE1vZGU6IHJlc29sdmVkLnNzbE1vZGUsXG4gIH07XG59XG5cbi8qKiBCdWlsZCB0aGUge0BsaW5rIFJlc29sdmVkQXBwRW52fSBpbnRlcmNlcHRvcnMgcmVhZCwgZnJvbSB0aGUgYXV0by1jb25maWcgcmVzdWx0LiAqL1xuZnVuY3Rpb24gcmVzb2x2ZWRBcHBFbnYobGFrZWJhc2U6IExha2ViYXNlQ29ubmVjdGlvbiB8IHVuZGVmaW5lZCk6IFJlc29sdmVkQXBwRW52IHtcbiAgcmV0dXJuIHtcbiAgICAuLi4obGFrZWJhc2UgPyB7IGxha2ViYXNlIH0gOiB7fSksXG4gICAgLi4uKHByb2Nlc3MuZW52LkRBVEFCUklDS1NfSE9TVCA/IHsgZGF0YWJyaWNrc0hvc3Q6IHByb2Nlc3MuZW52LkRBVEFCUklDS1NfSE9TVCB9IDoge30pLFxuICB9O1xufVxuXG4vKiogTm9ybWFsaXplIHRoZSBgaW50ZXJjZXB0b3I/OiBJbnRlcmNlcHRvciB8IEludGVyY2VwdG9yW11gIG9wdGlvbiB0byBhbiBhcnJheS4gKi9cbmZ1bmN0aW9uIGludGVyY2VwdG9yTGlzdChpbnRlcmNlcHRvcjogQ3JlYXRlQXBwQ29uZmlnW1wiaW50ZXJjZXB0b3JcIl0pOiBJbnRlcmNlcHRvcltdIHtcbiAgaWYgKCFpbnRlcmNlcHRvcikgcmV0dXJuIFtdO1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShpbnRlcmNlcHRvcikgPyBpbnRlcmNlcHRvciA6IFtpbnRlcmNlcHRvcl07XG59XG5cbi8qKlxuICogQXV0by1jb25maWd1cmluZyBkcm9wLWluIGZvciBBcHBLaXQncyBgY3JlYXRlQXBwYDogc2FtZSBjb25maWcsIHNhbWUgdHlwZWRcbiAqIHBsdWdpbi1leHBvcnQgbWFwLCB3aXRoIHtAbGluayBhdXRvQ29uZmlndXJlfSBydW4gZmlyc3QuXG4gKlxuICogV2hlbiB7QGxpbmsgQ3JlYXRlQXBwQ29uZmlnLmludGVyY2VwdG9yfXMgYXJlIGdpdmVuLCBlYWNoIGlzIGludm9rZWQgd2l0aCBhblxuICoge0BsaW5rIEludGVyY2VwdG9yQ29udGV4dH0gQUZURVIgYXV0by1jb25maWd1cmF0aW9uIGNvbXB1dGVzIHRoZSBlbnYgYW5kIEJFRk9SRVxuICogQXBwS2l0IGJvb3RzIC0gc28gYW4gaW50ZXJjZXB0b3IgY2FuIHJlYWQgdGhlIHJlc29sdmVkIGNvbm5lY3Rpb24sIHJlZ2lzdGVyXG4gKiBsaWZlY3ljbGUgaGFuZGxlcnMsIGFuZCBzdGFydCBhdXhpbGlhcnkgd29yay4gQSBoaWRkZW4ge0BsaW5rIGxpZmVjeWNsZUJyaWRnZX1cbiAqIHBsdWdpbiBpcyBpbmplY3RlZCBzbyB0aG9zZSBgb25MaWZlY3ljbGVgIGhhbmRsZXJzIGZpcmUgb24gdGhlIGdlbnVpbmUgQXBwS2l0XG4gKiBldmVudHM7IGl0IGhhcyBubyBleHBvcnRzLCBzbyB0aGUgcmV0dXJuZWQge0BsaW5rIFBsdWdpbk1hcH0gaXMgdW5jaGFuZ2VkLlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgeyBsYWtlYmFzZSwgc2VydmVyIH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuICogaW1wb3J0IHsgYXBwa2l0IH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG4gKlxuICogY29uc3QgYXBwID0gYXdhaXQgYXBwa2l0LmNyZWF0ZUFwcCh7IHBsdWdpbnM6IFtzZXJ2ZXIoKSwgbGFrZWJhc2UoKV0gfSk7XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVBcHA8VCBleHRlbmRzIEFwcEtpdFBsdWdpbnM+KFxuICBjb25maWc/OiBDcmVhdGVBcHBDb25maWc8VD4sXG4pOiBQcm9taXNlPFBsdWdpbk1hcDxUPj4ge1xuICBpbnN0YWxsQXNVc2VyRGV2ZWxvcG1lbnRQYXRjaCgpO1xuICBhd2FpdCBjb25maWd1cmVOYXRpdmVIdHRwVGVsZW1ldHJ5KHsgc3Bhbkhvb2s6IHN0YW1wSHR0cFRyYWNlVXNlciB9KTtcbiAgY29uc3QgcGx1Z2lucyA9IHBsdWdpbk5hbWVzKGNvbmZpZyk7XG4gIGNvbnN0IGludGVyY2VwdG9ycyA9IGludGVyY2VwdG9yTGlzdChjb25maWc/LmludGVyY2VwdG9yKTtcbiAgbG9nZ2VyLmRlYnVnKFwiY3JlYXRlQXBwOiBzdGFydFwiLCB7XG4gICAgcGx1Z2lucyxcbiAgICBwbHVnaW5Db3VudDogcGx1Z2lucy5sZW5ndGgsXG4gICAgaW50ZXJjZXB0b3JDb3VudDogaW50ZXJjZXB0b3JzLmxlbmd0aCxcbiAgICBhdXRvQ29uZmlndXJlOiBjb25maWc/LmF1dG9Db25maWd1cmUgPz8gXCIoZGVmYXVsdClcIixcbiAgICBoYXNPblBsdWdpbnNSZWFkeTogdHlwZW9mIGNvbmZpZz8ub25QbHVnaW5zUmVhZHkgPT09IFwiZnVuY3Rpb25cIixcbiAgfSk7XG5cbiAgbG9nZ2VyLmRlYnVnKFwiY3JlYXRlQXBwOiBhdXRvQ29uZmlndXJlXCIpO1xuICBjb25zdCBicmFuZENvbnRleHQgPSBhd2FpdCBsb2FkQnJhbmRDb250ZXh0KCk7XG4gIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZUFwcDogYnJhbmQgY29udGV4dCBsb2FkZWRcIiwgeyBuYW1lOiBicmFuZENvbnRleHQubmFtZSB9KTtcbiAgY29uc3QgbGFrZWJhc2UgPSBhd2FpdCBhdXRvQ29uZmlndXJlKGNvbmZpZyk7XG4gIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZUFwcDogYXV0b0NvbmZpZ3VyZSByZXR1cm5lZFwiLCB7XG4gICAgbGFrZWJhc2U6IGxha2ViYXNlID8gcmVkYWN0TGFrZWJhc2VDb25uZWN0aW9uKGxha2ViYXNlKSA6IHVuZGVmaW5lZCxcbiAgfSk7XG5cbiAgY29uc3QgYXBwQ29uZmlnID0geyAuLi5jb25maWcgfTtcbiAgZGVsZXRlIGFwcENvbmZpZy5hdXRvQ29uZmlndXJlO1xuICBkZWxldGUgYXBwQ29uZmlnLmRlYnVnO1xuICBkZWxldGUgYXBwQ29uZmlnLmludGVyY2VwdG9yO1xuICBjb25zdCBvblBsdWdpbnNSZWFkeSA9IGFwcENvbmZpZy5vblBsdWdpbnNSZWFkeTtcbiAgYXBwQ29uZmlnLm9uUGx1Z2luc1JlYWR5ID0gYXN5bmMgKGFwcCkgPT4ge1xuICAgIGNvbnN0IGJvdW5kID0gYXdhaXQgYmluZE5hdGl2ZVRlbGVtZXRyeVByb3ZpZGVyKCk7XG4gICAgbG9nZ2VyLmRlYnVnKFwiY3JlYXRlQXBwOiBuYXRpdmUgdGVsZW1ldHJ5IHByb3ZpZGVyIGJpbmRpbmdcIiwgeyBib3VuZCB9KTtcbiAgICBhd2FpdCBvblBsdWdpbnNSZWFkeT8uKGFwcCk7XG4gIH07XG5cbiAgaWYgKHNob3VsZEluamVjdENhY2hlU3RvcmFnZShjb25maWcpKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwiY3JlYXRlQXBwOiBpbmplY3QgbWVtb3J5LWZpcnN0IGNhY2hlIHN0b3JhZ2VcIik7XG4gICAgY29uc3Qgc3RvcmFnZSA9IGF3YWl0IGNyZWF0ZUFwcEtpdENhY2hlU3RvcmFnZSh7XG4gICAgICBjYWNoZTogY29uZmlnPy5jYWNoZSxcbiAgICAgIHByZWZlckxha2ViYXNlOiBCb29sZWFuKGxha2ViYXNlKSB8fCB1c2VzUGx1Z2luKGNvbmZpZywgTEFLRUJBU0VfUExVR0lOKSxcbiAgICB9KTtcbiAgICBhcHBDb25maWcuY2FjaGUgPSB7IC4uLmNvbmZpZz8uY2FjaGUsIHN0b3JhZ2UgfTtcbiAgICBsb2dnZXIuZGVidWcoXCJjcmVhdGVBcHA6IG1lbW9yeS1maXJzdCBjYWNoZSBzdG9yYWdlIHJlYWR5XCIsIHtcbiAgICAgIHBlcnNpc3RlbnQ6IHN0b3JhZ2UuaXNQZXJzaXN0ZW50KCksXG4gICAgfSk7XG4gIH1cblxuICBpZiAoZGVidWdDYXB0dXJlRW5hYmxlZChjb25maWc/LmRlYnVnKSAmJiAhdXNlc1BsdWdpbihjb25maWcsIERFQlVHX0NBUFRVUkVfUExVR0lOX05BTUUpKSB7XG4gICAgYXBwQ29uZmlnLnBsdWdpbnMgPSBbLi4uKGFwcENvbmZpZy5wbHVnaW5zID8/IFtdKSwgZGVidWdDYXB0dXJlKCldIGFzIHVua25vd24gYXMgVDtcbiAgICBsb2dnZXIuZGVidWcoXCJjcmVhdGVBcHA6IGJyb3dzZXIgZGVidWcgY2FwdHVyZSBpbmplY3RlZFwiLCB7XG4gICAgICBtb2RlOiBjb25maWc/LmRlYnVnID8/IFwiYXV0b1wiLFxuICAgICAgbm9kZUVudmlyb25tZW50OiBwcm9jZXNzLmVudi5OT0RFX0VOVixcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChpbnRlcmNlcHRvcnMubGVuZ3RoID09PSAwKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwiY3JlYXRlQXBwOiBubyBpbnRlcmNlcHRvcnM7IGRlbGVnYXRpbmcgdG8gQXBwS2l0IGNyZWF0ZUFwcFwiLCB7XG4gICAgICBwbHVnaW5zOiBwbHVnaW5OYW1lcyhhcHBDb25maWcpLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGFwcGtpdENyZWF0ZUFwcDxUPihhcHBDb25maWcpO1xuICAgIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZUFwcDogQXBwS2l0IGNyZWF0ZUFwcCByZXR1cm5lZFwiLCB7XG4gICAgICBleHBvcnRLZXlzOiBPYmplY3Qua2V5cyhyZXN1bHQgPz8ge30pLFxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvLyBCdWlsZCB0aGUgY29udGV4dCBmcm9tIHRoZSBjb21wdXRlZCBlbnYsIHJ1biBlYWNoIGludGVyY2VwdG9yICh0aGV5IHJlZ2lzdGVyXG4gIC8vIGxpZmVjeWNsZSBoYW5kbGVycyArIGJpbmQgcHJvY2Vzc2VzKSwgdGhlbiBpbmplY3QgdGhlIGJyaWRnZSB0aGF0IHJlbGF5cyB0aGVcbiAgLy8gUkVBTCBBcHBLaXQgbGlmZWN5Y2xlIGludG8gYHJ1bnRpbWUuZW1pdExpZmVjeWNsZWAgZHVyaW5nIGl0cyBgc2V0dXAoKWAuXG4gIGNvbnN0IGVudiA9IHJlc29sdmVkQXBwRW52KGxha2ViYXNlKTtcbiAgbG9nZ2VyLmRlYnVnKFwiY3JlYXRlQXBwOiBpbnRlcmNlcHRvciBjb250ZXh0XCIsIHtcbiAgICBoYXNMYWtlYmFzZTogQm9vbGVhbihlbnYubGFrZWJhc2UpLFxuICAgIGRhdGFicmlja3NIb3N0OiBlbnYuZGF0YWJyaWNrc0hvc3QsXG4gICAgaW50ZXJjZXB0b3JDb3VudDogaW50ZXJjZXB0b3JzLmxlbmd0aCxcbiAgfSk7XG4gIGNvbnN0IHJ1bnRpbWU6IEludGVyY2VwdG9yUnVudGltZSA9IGNyZWF0ZUludGVyY2VwdG9yQ29udGV4dChlbnYpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGludGVyY2VwdG9ycy5sZW5ndGg7IGkrKykge1xuICAgIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZUFwcDogcnVuIGludGVyY2VwdG9yXCIsIHsgaW5kZXg6IGksIG9mOiBpbnRlcmNlcHRvcnMubGVuZ3RoIH0pO1xuICAgIGF3YWl0IGludGVyY2VwdG9yc1tpXSEocnVudGltZS5jb250ZXh0KTtcbiAgICBsb2dnZXIuZGVidWcoXCJjcmVhdGVBcHA6IGludGVyY2VwdG9yIGRvbmVcIiwgeyBpbmRleDogaSB9KTtcbiAgfVxuICAvLyBBcHBlbmQgdGhlIGJyaWRnZSB0byB0aGUgcGx1Z2lucyB0dXBsZS4gSXQgaXMgaGlkZGVuIGFuZCBleHBvcnRzIG5vdGhpbmcsIHNvXG4gIC8vIHRoZSByZXR1cm5lZCBtYXAgc3RpbGwgbWF0Y2hlcyBgUGx1Z2luTWFwPFQ+YDsgdGhlIGNhc3QgKHRocm91Z2ggYHVua25vd25gKSBpc1xuICAvLyBvbmx5IGJlY2F1c2UgYXBwZW5kaW5nIHdpZGVucyB0aGUgdHVwbGUgdHlwZSBiZXlvbmQgYFRgLlxuICBhcHBDb25maWcucGx1Z2lucyA9IFsuLi4oYXBwQ29uZmlnLnBsdWdpbnMgPz8gW10pLCBsaWZlY3ljbGVCcmlkZ2UoeyBydW50aW1lIH0pXSBhcyB1bmtub3duIGFzIFQ7XG4gIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZUFwcDogbGlmZWN5Y2xlIGJyaWRnZSBpbmplY3RlZDsgZGVsZWdhdGluZyB0byBBcHBLaXQgY3JlYXRlQXBwXCIsIHtcbiAgICBwbHVnaW5zOiBwbHVnaW5OYW1lcyhhcHBDb25maWcpLFxuICB9KTtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYXBwa2l0Q3JlYXRlQXBwPFQ+KGFwcENvbmZpZyk7XG4gIGxvZ2dlci5kZWJ1ZyhcImNyZWF0ZUFwcDogQXBwS2l0IGNyZWF0ZUFwcCByZXR1cm5lZFwiLCB7XG4gICAgZXhwb3J0S2V5czogT2JqZWN0LmtleXMocmVzdWx0ID8/IHt9KSxcbiAgfSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogVGhlIEFwcEtpdCBwZXItcmVxdWVzdCBleGVjdXRpb24gY29udGV4dCByZXR1cm5lZCBieSBgZ2V0RXhlY3V0aW9uQ29udGV4dCgpYFxuICogLSB0aGUgT0JPLXNjb3BlZCB3b3Jrc3BhY2UgY2xpZW50IHBsdXMgdGhlIHN1cnJvdW5kaW5nIHJlcXVlc3QgbWV0YWRhdGEuXG4gKiBEZXJpdmVkIGZyb20gQXBwS2l0J3Mgb3duIHJldHVybiB0eXBlIHNvIGl0IHRyYWNrcyB0aGUgaW5zdGFsbGVkIHZlcnNpb24sIGFuZFxuICogcmUtZXhwb3J0ZWQgaGVyZSBzbyBhZGQtb24gcGFja2FnZXMgY2FuIHR5cGUgYSBjb250ZXh0IHBhcmFtZXRlciB3aXRob3V0IGVhY2hcbiAqIHJlLWRlcml2aW5nIHRoZSBzYW1lIGBSZXR1cm5UeXBlPHR5cGVvZiBnZXRFeGVjdXRpb25Db250ZXh0PmAgaW5saW5lLlxuICovXG5leHBvcnQgdHlwZSBFeGVjdXRpb25Db250ZXh0TGlrZSA9IFJldHVyblR5cGU8dHlwZW9mIGdldEV4ZWN1dGlvbkNvbnRleHQ+O1xuXG4vKipcbiAqIFRoZSBhdXRoLXNjb3BlZCBEYXRhYnJpY2tzIHdvcmtzcGFjZSBjbGllbnQgY2FycmllZCBvbiBhblxuICogYEV4ZWN1dGlvbkNvbnRleHRMaWtlYCAoYGdldEV4ZWN1dGlvbkNvbnRleHQoKS5jbGllbnRgKS4gVHlwZWQgc3RydWN0dXJhbGx5XG4gKiBvZmYgQXBwS2l0IHNvIGNvbnN1bWVycyBkb24ndCB0YWtlIGEgZGlyZWN0IGBAZGF0YWJyaWNrcy9zZGstZXhwZXJpbWVudGFsYFxuICogZGVwZW5kZW5jeSAtIHRoZSBkZXAgZmxvd3MgaW4gdHJhbnNpdGl2ZWx5IHRocm91Z2ggYEBkYXRhYnJpY2tzL2FwcGtpdGAuXG4gKi9cbmV4cG9ydCB0eXBlIFdvcmtzcGFjZUNsaWVudExpa2UgPSBFeGVjdXRpb25Db250ZXh0TGlrZVtcImNsaWVudFwiXTtcblxuLyoqXG4gKiBUaGUgY3VycmVudCBBcHBLaXQgZXhlY3V0aW9uIGNvbnRleHQsIG9yIGB1bmRlZmluZWRgIHdoZW4gQXBwS2l0IGlzbid0XG4gKiBpbml0aWFsaXplZCAob3V0c2lkZSBhIHJlcXVlc3Qgc2NvcGUpLiBTd2FsbG93cyBBcHBLaXQnc1xuICoge0BsaW5rIEluaXRpYWxpemF0aW9uRXJyb3J9OyBhbnkgb3RoZXIgZXJyb3IgcHJvcGFnYXRlcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IHsgYXBwa2l0IH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG4gKiBpbXBvcnQgeyBjcmVhdGVXb3Jrc3BhY2VDbGllbnQgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG4gKlxuICogLy8gT0JPLXNjb3BlZCBpbnNpZGUgYSByZXF1ZXN0LCBzZXJ2aWNlIHByaW5jaXBhbCBmcm9tIGEgQ0xJIG9yIHNjcmlwdC5cbiAqIGNvbnN0IGNsaWVudCA9IGFwcGtpdC50cnlHZXRFeGVjdXRpb25Db250ZXh0KCk/LmNsaWVudCA/PyBjcmVhdGVXb3Jrc3BhY2VDbGllbnQoKTtcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyeUdldEV4ZWN1dGlvbkNvbnRleHQoKTogRXhlY3V0aW9uQ29udGV4dExpa2UgfCB1bmRlZmluZWQge1xuICB0cnkge1xuICAgIGNvbnN0IGN0eCA9IGdldEV4ZWN1dGlvbkNvbnRleHQoKTtcbiAgICBpZiAoY3R4Py5jbGllbnQpIHtcbiAgICAgIHJldHVybiBjdHg7XG4gICAgfVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmICghKGVycm9yIGluc3RhbmNlb2YgSW5pdGlhbGl6YXRpb25FcnJvcikpIHtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIEluaXRpYWxpemUgYSBiYXJlIEFwcEtpdCBhcHAgKG5vIHBsdWdpbnMpIHdoZW4gbm9uZSBpcyBydW5uaW5nIHlldC5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IHsgYXBwa2l0IH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG4gKlxuICogYXdhaXQgYXBwa2l0LmVuc3VyZUluaXRpYWxpemVkKCk7XG4gKiBjb25zdCBjbGllbnQgPSBhcHBraXQudHJ5R2V0RXhlY3V0aW9uQ29udGV4dCgpPy5jbGllbnQ7XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbnN1cmVJbml0aWFsaXplZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKHRyeUdldEV4ZWN1dGlvbkNvbnRleHQoKSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcImVuc3VyZUluaXRpYWxpemVkOiBhbHJlYWR5IGluaXRpYWxpemVkXCIpO1xuICAgIHJldHVybjtcbiAgfVxuICBsb2dnZXIuZGVidWcoXCJlbnN1cmVJbml0aWFsaXplZDogYm9vdGluZyBiYXJlIEFwcEtpdCBhcHBcIik7XG4gIGF3YWl0IGNyZWF0ZUFwcCh7IHBsdWdpbnM6IFtdLCBhdXRvQ29uZmlndXJlOiBmYWxzZSB9KTtcbiAgbG9nZ2VyLmRlYnVnKFwiZW5zdXJlSW5pdGlhbGl6ZWQ6IGJhcmUgQXBwS2l0IGluaXRpYWxpemF0aW9uIGNvbXBsZXRlXCIpO1xufVxuIl19
@@ -0,0 +1,36 @@
1
+ import { Plugin, type BasePluginConfig, type IAppRouter } from "@databricks/appkit";
2
+ import { type DebugCaptureClientConfig } from "@dbx-tools/shared-appkit/debug";
3
+ /** Configuration for the AppKit browser debug-capture plugin. */
4
+ export interface DebugCapturePluginConfig extends BasePluginConfig {
5
+ /** Directory where JSONL captures are written. */
6
+ directory?: string;
7
+ }
8
+ /** Exports available when the debug-capture plugin is registered explicitly. */
9
+ export interface DebugCapturePluginExports {
10
+ /** Directory containing capture JSONL files. */
11
+ directory: string;
12
+ /** Resolve a capture identifier to its JSONL file path. */
13
+ path(captureId: string): string;
14
+ }
15
+ /** AppKit plugin that receives browser diagnostic event batches. */
16
+ export declare class DebugCapturePlugin extends Plugin<DebugCapturePluginConfig> {
17
+ #private;
18
+ static manifest: {
19
+ name: "debugCapture";
20
+ displayName: string;
21
+ description: string;
22
+ stability: "beta";
23
+ hidden: true;
24
+ resources: {
25
+ required: never[];
26
+ optional: never[];
27
+ };
28
+ };
29
+ constructor(config?: DebugCapturePluginConfig);
30
+ private get basePath();
31
+ clientConfig(): DebugCaptureClientConfig;
32
+ exports(): DebugCapturePluginExports;
33
+ injectRoutes(router: IAppRouter): void;
34
+ }
35
+ /** AppKit registration factory for {@link DebugCapturePlugin}. */
36
+ export declare const debugCapture: import("@databricks/appkit").ToPlugin<typeof DebugCapturePlugin, DebugCapturePluginConfig | undefined, "debugCapture">;
@@ -0,0 +1,67 @@
1
+ import { Plugin, toPlugin, } from "@databricks/appkit";
2
+ import { DEBUG_CAPTURE_PLUGIN_NAME, DEBUG_CAPTURE_ROUTE, DEBUG_CAPTURE_DEFAULT_BASE_PATH, DebugCaptureAppendResponseSchema, DebugCaptureClientConfigSchema, DebugCaptureRequestSchema, DebugCaptureStartResponseSchema, DebugCaptureStopResponseSchema, } from "@dbx-tools/shared-appkit/debug";
3
+ import { DebugCaptureStorage } from "./storage.js";
4
+ /** AppKit plugin that receives browser diagnostic event batches. */
5
+ export class DebugCapturePlugin extends Plugin {
6
+ static manifest = {
7
+ name: DEBUG_CAPTURE_PLUGIN_NAME,
8
+ displayName: "Browser Debug Capture",
9
+ description: "Records bounded browser, viewport, focus, input, and pointer diagnostics.",
10
+ stability: "beta",
11
+ hidden: true,
12
+ resources: { required: [], optional: [] },
13
+ };
14
+ #storage;
15
+ constructor(config = {}) {
16
+ super(config);
17
+ this.#storage = new DebugCaptureStorage(config.directory);
18
+ }
19
+ get basePath() {
20
+ const endpoint = this.getEndpoints().captures;
21
+ return endpoint?.endsWith(DEBUG_CAPTURE_ROUTE)
22
+ ? endpoint.slice(0, -DEBUG_CAPTURE_ROUTE.length)
23
+ : DEBUG_CAPTURE_DEFAULT_BASE_PATH;
24
+ }
25
+ clientConfig() {
26
+ return DebugCaptureClientConfigSchema.parse({ basePath: this.basePath });
27
+ }
28
+ exports() {
29
+ return {
30
+ directory: this.#storage.directory,
31
+ path: (captureId) => this.#storage.path(captureId),
32
+ };
33
+ }
34
+ injectRoutes(router) {
35
+ this.route(router, {
36
+ name: "captures",
37
+ method: "post",
38
+ path: DEBUG_CAPTURE_ROUTE,
39
+ handler: async (request, response) => {
40
+ response.setHeader("cache-control", "no-store");
41
+ const parsed = DebugCaptureRequestSchema.safeParse(request.body);
42
+ if (!parsed.success) {
43
+ response.status(400).json({ error: "Invalid debug capture request." });
44
+ return;
45
+ }
46
+ if (parsed.data.action === "start") {
47
+ const captureId = await this.#storage.start({
48
+ ...parsed.data.metadata,
49
+ userAgent: request.header("user-agent")?.slice(0, 500) ?? "unknown",
50
+ });
51
+ response.json(DebugCaptureStartResponseSchema.parse({ captureId }));
52
+ return;
53
+ }
54
+ if (parsed.data.action === "append") {
55
+ await this.#storage.append(parsed.data.captureId, parsed.data.events);
56
+ response.json(DebugCaptureAppendResponseSchema.parse({ ok: true }));
57
+ return;
58
+ }
59
+ await this.#storage.stop(parsed.data.captureId, parsed.data.events);
60
+ response.json(DebugCaptureStopResponseSchema.parse({ captureId: parsed.data.captureId, ok: true }));
61
+ },
62
+ });
63
+ }
64
+ }
65
+ /** AppKit registration factory for {@link DebugCapturePlugin}. */
66
+ export const debugCapture = toPlugin(DebugCapturePlugin);
67
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2RlYnVnL3BsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsTUFBTSxFQUNOLFFBQVEsR0FJVCxNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIsbUJBQW1CLEVBQ25CLCtCQUErQixFQUMvQixnQ0FBZ0MsRUFDaEMsOEJBQThCLEVBQzlCLHlCQUF5QixFQUN6QiwrQkFBK0IsRUFDL0IsOEJBQThCLEdBRS9CLE1BQU0sZ0NBQWdDLENBQUM7QUFFeEMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBZ0JuRCxvRUFBb0U7QUFDcEUsTUFBTSxPQUFPLGtCQUFtQixTQUFRLE1BQWdDO0lBQ3RFLE1BQU0sQ0FBQyxRQUFRLEdBQUc7UUFDaEIsSUFBSSxFQUFFLHlCQUF5QjtRQUMvQixXQUFXLEVBQUUsdUJBQXVCO1FBQ3BDLFdBQVcsRUFBRSwyRUFBMkU7UUFDeEYsU0FBUyxFQUFFLE1BQU07UUFDakIsTUFBTSxFQUFFLElBQUk7UUFDWixTQUFTLEVBQUUsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUU7S0FDaUIsQ0FBQztJQUVwRCxRQUFRLENBQXNCO0lBRXZDLFlBQVksU0FBbUMsRUFBRTtRQUMvQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDZCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksbUJBQW1CLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRCxJQUFZLFFBQVE7UUFDbEIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLFFBQVEsQ0FBQztRQUM5QyxPQUFPLFFBQVEsRUFBRSxRQUFRLENBQUMsbUJBQW1CLENBQUM7WUFDNUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMs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XG4gIHRvUGx1Z2luLFxuICB0eXBlIEJhc2VQbHVnaW5Db25maWcsXG4gIHR5cGUgSUFwcFJvdXRlcixcbiAgdHlwZSBQbHVnaW5NYW5pZmVzdCxcbn0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHtcbiAgREVCVUdfQ0FQVFVSRV9QTFVHSU5fTkFNRSxcbiAgREVCVUdfQ0FQVFVSRV9ST1VURSxcbiAgREVCVUdfQ0FQVFVSRV9ERUZBVUxUX0JBU0VfUEFUSCxcbiAgRGVidWdDYXB0dXJlQXBwZW5kUmVzcG9uc2VTY2hlbWEsXG4gIERlYnVnQ2FwdHVyZUNsaWVudENvbmZpZ1NjaGVtYSxcbiAgRGVidWdDYXB0dXJlUmVxdWVzdFNjaGVtYSxcbiAgRGVidWdDYXB0dXJlU3RhcnRSZXNwb25zZVNjaGVtYSxcbiAgRGVidWdDYXB0dXJlU3RvcFJlc3BvbnNlU2NoZW1hLFxuICB0eXBlIERlYnVnQ2FwdHVyZUNsaWVudENvbmZpZyxcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWFwcGtpdC9kZWJ1Z1wiO1xuXG5pbXBvcnQgeyBEZWJ1Z0NhcHR1cmVTdG9yYWdlIH0gZnJvbSBcIi4vc3RvcmFnZS50c1wiO1xuXG4vKiogQ29uZmlndXJhdGlvbiBmb3IgdGhlIEFwcEtpdCBicm93c2VyIGRlYnVnLWNhcHR1cmUgcGx1Z2luLiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZWJ1Z0NhcHR1cmVQbHVnaW5Db25maWcgZXh0ZW5kcyBCYXNlUGx1Z2luQ29uZmlnIHtcbiAgLyoqIERpcmVjdG9yeSB3aGVyZSBKU09OTCBjYXB0dXJlcyBhcmUgd3JpdHRlbi4gKi9cbiAgZGlyZWN0b3J5Pzogc3RyaW5nO1xufVxuXG4vKiogRXhwb3J0cyBhdmFpbGFibGUgd2hlbiB0aGUgZGVidWctY2FwdHVyZSBwbHVnaW4gaXMgcmVnaXN0ZXJlZCBleHBsaWNpdGx5LiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZWJ1Z0NhcHR1cmVQbHVnaW5FeHBvcnRzIHtcbiAgLyoqIERpcmVjdG9yeSBjb250YWluaW5nIGNhcHR1cmUgSlNPTkwgZmlsZXMuICovXG4gIGRpcmVjdG9yeTogc3RyaW5nO1xuICAvKiogUmVzb2x2ZSBhIGNhcHR1cmUgaWRlbnRpZmllciB0byBpdHMgSlNPTkwgZmlsZSBwYXRoLiAqL1xuICBwYXRoKGNhcHR1cmVJZDogc3RyaW5nKTogc3RyaW5nO1xufVxuXG4vKiogQXBwS2l0IHBsdWdpbiB0aGF0IHJlY2VpdmVzIGJyb3dzZXIgZGlhZ25vc3RpYyBldmVudCBiYXRjaGVzLiAqL1xuZXhwb3J0IGNsYXNzIERlYnVnQ2FwdHVyZVBsdWdpbiBleHRlbmRzIFBsdWdpbjxEZWJ1Z0NhcHR1cmVQbHVnaW5Db25maWc+IHtcbiAgc3RhdGljIG1hbmlmZXN0ID0ge1xuICAgIG5hbWU6IERFQlVHX0NBUFRVUkVfUExVR0lOX05BTUUsXG4gICAgZGlzcGxheU5hbWU6IFwiQnJvd3NlciBEZWJ1ZyBDYXB0dXJlXCIsXG4gICAgZGVzY3JpcHRpb246IFwiUmVjb3JkcyBib3VuZGVkIGJyb3dzZXIsIHZpZXdwb3J0LCBmb2N1cywgaW5wdXQsIGFuZCBwb2ludGVyIGRpYWdub3N0aWNzLlwiLFxuICAgIHN0YWJpbGl0eTogXCJiZXRhXCIsXG4gICAgaGlkZGVuOiB0cnVlLFxuICAgIHJlc291cmNlczogeyByZXF1aXJlZDogW10sIG9wdGlvbmFsOiBbXSB9LFxuICB9IHNhdGlzZmllcyBQbHVnaW5NYW5pZmVzdDx0eXBlb2YgREVCVUdfQ0FQVFVSRV9QTFVHSU5fTkFNRT47XG5cbiAgcmVhZG9ubHkgI3N0b3JhZ2U6IERlYnVnQ2FwdHVyZVN0b3JhZ2U7XG5cbiAgY29uc3RydWN0b3IoY29uZmlnOiBEZWJ1Z0NhcHR1cmVQbHVnaW5Db25maWcgPSB7fSkge1xuICAgIHN1cGVyKGNvbmZpZyk7XG4gICAgdGhpcy4jc3RvcmFnZSA9IG5ldyBEZWJ1Z0NhcHR1cmVTdG9yYWdlKGNvbmZpZy5kaXJlY3RvcnkpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgYmFzZVBhdGgoKTogc3RyaW5nIHtcbiAgICBjb25zdCBlbmRwb2ludCA9IHRoaXMuZ2V0RW5kcG9pbnRzKCkuY2FwdHVyZXM7XG4gICAgcmV0dXJuIGVuZHBvaW50Py5lbmRzV2l0aChERUJVR19DQVBUVVJFX1JPVVRFKVxuICAgICAgPyBlbmRwb2ludC5zbGljZSgwLCAtREVCVUdfQ0FQVFVSRV9ST1VURS5sZW5ndGgpXG4gICAgICA6IERFQlVHX0NBUFRVUkVfREVGQVVMVF9CQVNFX1BBVEg7XG4gIH1cblxuICBvdmVycmlkZSBjbGllbnRDb25maWcoKTogRGVidWdDYXB0dXJlQ2xpZW50Q29uZmlnIHtcbiAgICByZXR1cm4gRGVidWdDYXB0dXJlQ2xpZW50Q29uZmlnU2NoZW1hLnBhcnNlKHsgYmFzZVBhdGg6IHRoaXMuYmFzZVBhdGggfSk7XG4gIH1cblxuICBvdmVycmlkZSBleHBvcnRzKCk6IERlYnVnQ2FwdHVyZVBsdWdpbkV4cG9ydHMge1xuICAgIHJldHVybiB7XG4gICAgICBkaXJlY3Rvcnk6IHRoaXMuI3N0b3JhZ2UuZGlyZWN0b3J5LFxuICAgICAgcGF0aDogKGNhcHR1cmVJZCkgPT4gdGhpcy4jc3RvcmFnZS5wYXRoKGNhcHR1cmVJZCksXG4gICAgfTtcbiAgfVxuXG4gIG92ZXJyaWRlIGluamVjdFJvdXRlcyhyb3V0ZXI6IElBcHBSb3V0ZXIpOiB2b2lkIHtcbiAgICB0aGlzLnJvdXRlKHJvdXRlciwge1xuICAgICAgbmFtZTogXCJjYXB0dXJlc1wiLFxuICAgICAgbWV0aG9kOiBcInBvc3RcIixcbiAgICAgIHBhdGg6IERFQlVHX0NBUFRVUkVfUk9VVEUsXG4gICAgICBoYW5kbGVyOiBhc3luYyAocmVxdWVzdCwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgcmVzcG9uc2Uuc2V0SGVhZGVyKFwiY2FjaGUtY29udHJvbFwiLCBcIm5vLXN0b3JlXCIpO1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBEZWJ1Z0NhcHR1cmVSZXF1ZXN0U2NoZW1hLnNhZmVQYXJzZShyZXF1ZXN0LmJvZHkpO1xuICAgICAgICBpZiAoIXBhcnNlZC5zdWNjZXNzKSB7XG4gICAgICAgICAgcmVzcG9uc2Uuc3RhdHVzKDQwMCkuanNvbih7IGVycm9yOiBcIkludmFsaWQgZGVidWcgY2FwdHVyZSByZXF1ZXN0LlwiIH0pO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJzZWQuZGF0YS5hY3Rpb24gPT09IFwic3RhcnRcIikge1xuICAgICAgICAgIGNvbnN0IGNhcHR1cmVJZCA9IGF3YWl0IHRoaXMuI3N0b3JhZ2Uuc3RhcnQoe1xuICAgICAgICAgICAgLi4ucGFyc2VkLmRhdGEubWV0YWRhdGEsXG4gICAgICAgICAgICB1c2VyQWdlbnQ6IHJlcXVlc3QuaGVhZGVyKFwidXNlci1hZ2VudFwiKT8uc2xpY2UoMCwgNTAwKSA/PyBcInVua25vd25cIixcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXNwb25zZS5qc29uKERlYnVnQ2FwdHVyZVN0YXJ0UmVzcG9uc2VTY2hlbWEucGFyc2UoeyBjYXB0dXJlSWQgfSkpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJzZWQuZGF0YS5hY3Rpb24gPT09IFwiYXBwZW5kXCIpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLiNzdG9yYWdlLmFwcGVuZChwYXJzZWQuZGF0YS5jYXB0dXJlSWQsIHBhcnNlZC5kYXRhLmV2ZW50cyk7XG4gICAgICAgICAgcmVzcG9uc2UuanNvbihEZWJ1Z0NhcHR1cmVBcHBlbmRSZXNwb25zZVNjaGVtYS5wYXJzZSh7IG9rOiB0cnVlIH0pKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLiNzdG9yYWdlLnN0b3AocGFyc2VkLmRhdGEuY2FwdHVyZUlkLCBwYXJzZWQuZGF0YS5ldmVudHMpO1xuICAgICAgICByZXNwb25zZS5qc29uKFxuICAgICAgICAgIERlYnVnQ2FwdHVyZVN0b3BSZXNwb25zZVNjaGVtYS5wYXJzZSh7IGNhcHR1cmVJZDogcGFyc2VkLmRhdGEuY2FwdHVyZUlkLCBvazogdHJ1ZSB9KSxcbiAgICAgICAgKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqIEFwcEtpdCByZWdpc3RyYXRpb24gZmFjdG9yeSBmb3Ige0BsaW5rIERlYnVnQ2FwdHVyZVBsdWdpbn0uICovXG5leHBvcnQgY29uc3QgZGVidWdDYXB0dXJlID0gdG9QbHVnaW4oRGVidWdDYXB0dXJlUGx1Z2luKTtcbiJdfQ==
@@ -0,0 +1,20 @@
1
+ import { type DebugCaptureEvent, type DebugCaptureScalar } from "@dbx-tools/shared-appkit/debug";
2
+ type DebugCaptureMetadata = Record<string, DebugCaptureScalar>;
3
+ /** Default local directory for browser debug capture JSONL files. */
4
+ export declare function defaultDebugCaptureDirectory(): string;
5
+ /** Filesystem-backed JSONL storage for AppKit browser debug captures. */
6
+ export declare class DebugCaptureStorage {
7
+ #private;
8
+ readonly directory: string;
9
+ constructor(directory?: string);
10
+ /** Resolve a validated capture identifier to its JSONL file. */
11
+ path(captureId: string): string;
12
+ /** Create a new capture and write its metadata record. */
13
+ start(metadata: DebugCaptureMetadata): Promise<string>;
14
+ /** Append an ordered browser event batch to an active capture. */
15
+ append(captureId: string, events: readonly DebugCaptureEvent[]): Promise<void>;
16
+ /** Append final events and mark a capture complete. */
17
+ stop(captureId: string, events: readonly DebugCaptureEvent[]): Promise<void>;
18
+ private enqueue;
19
+ }
20
+ export {};
@@ -0,0 +1,68 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { appendFile, mkdir, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { DebugCaptureIdSchema, } from "@dbx-tools/shared-appkit/debug";
6
+ /** Default local directory for browser debug capture JSONL files. */
7
+ export function defaultDebugCaptureDirectory() {
8
+ return process.env.NODE_ENV === "development"
9
+ ? join(process.cwd(), ".tmp", "debug-captures")
10
+ : join(tmpdir(), "dbx-tools-debug-captures");
11
+ }
12
+ function serializeLines(records) {
13
+ return `${records.map((record) => JSON.stringify(record)).join("\n")}\n`;
14
+ }
15
+ /** Filesystem-backed JSONL storage for AppKit browser debug captures. */
16
+ export class DebugCaptureStorage {
17
+ directory;
18
+ #pending = new Map();
19
+ constructor(directory = defaultDebugCaptureDirectory()) {
20
+ this.directory = directory;
21
+ }
22
+ /** Resolve a validated capture identifier to its JSONL file. */
23
+ path(captureId) {
24
+ return join(this.directory, `${DebugCaptureIdSchema.parse(captureId)}.jsonl`);
25
+ }
26
+ /** Create a new capture and write its metadata record. */
27
+ async start(metadata) {
28
+ const captureId = `vp-${Date.now().toString(36)}-${randomBytes(4).toString("hex")}`;
29
+ await mkdir(this.directory, { recursive: true });
30
+ await writeFile(this.path(captureId), serializeLines([
31
+ {
32
+ kind: "capture-start",
33
+ captureId,
34
+ createdAt: new Date().toISOString(),
35
+ metadata,
36
+ },
37
+ ]), { encoding: "utf8", flag: "wx" });
38
+ return captureId;
39
+ }
40
+ /** Append an ordered browser event batch to an active capture. */
41
+ append(captureId, events) {
42
+ if (events.length === 0)
43
+ return Promise.resolve();
44
+ return this.enqueue(captureId, () => appendFile(this.path(captureId), serializeLines(events.map((event) => ({ kind: "event", ...event }))), "utf8"));
45
+ }
46
+ /** Append final events and mark a capture complete. */
47
+ stop(captureId, events) {
48
+ return this.enqueue(captureId, async () => {
49
+ if (events.length > 0) {
50
+ await appendFile(this.path(captureId), serializeLines(events.map((event) => ({ kind: "event", ...event }))), "utf8");
51
+ }
52
+ await appendFile(this.path(captureId), serializeLines([{ kind: "capture-stop", stoppedAt: new Date().toISOString() }]), "utf8");
53
+ });
54
+ }
55
+ enqueue(captureId, operation) {
56
+ DebugCaptureIdSchema.parse(captureId);
57
+ const previous = this.#pending.get(captureId) ?? Promise.resolve();
58
+ const current = previous.catch(() => undefined).then(operation);
59
+ this.#pending.set(captureId, current);
60
+ const cleanup = () => {
61
+ if (this.#pending.get(captureId) === current)
62
+ this.#pending.delete(captureId);
63
+ };
64
+ void current.then(cleanup, cleanup);
65
+ return current;
66
+ }
67
+ }
68
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZWJ1Zy9zdG9yYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDMUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNqQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2pDLE9BQU8sRUFDTCxvQkFBb0IsR0FHckIsTUFBTSxnQ0FBZ0MsQ0FBQztBQUl4QyxxRUFBcUU7QUFDckUsTUFBTSxVQUFVLDRCQUE0QjtJQUMxQyxPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLGFBQWE7UUFDM0MsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixDQUFDO1FBQy9DLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsMEJBQTBCLENBQUMsQ0FBQztBQUNqRCxDQUFDO0FBRUQsU0FBUyxjQUFjLENBQUMsT0FBMkI7SUFDakQsT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztBQUMzRSxDQUFDO0FBRUQseUVBQXlFO0FBQ3pFLE1BQU0sT0FBTyxtQkFBbUI7SUFDckIsU0FBUyxDQUFTO0lBQ2xCLFFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBeUIsQ0FBQztJQUVyRCxZQUFZLFNBQVMsR0FBRyw0QkFBNEIsRUFBRTtRQUNwRCxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztJQUM3QixDQUFDO0lBRUQsZ0VBQWdFO0lBQ2hFLElBQUksQ0FBQyxTQUFpQjtRQUNwQixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEdBQUcsb0JBQW9CLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNoRixDQUFDO0lBRUQsMERBQTBEO0lBQzFELEtBQUssQ0FBQyxLQUFLLENBQUMsUUFBOEI7UUFDeEMsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNwRixNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDakQsTUFBTSxTQUFTLENBQ2IsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFDcEIsY0FBYyxDQUFDO1lBQ2I7Z0JBQ0UsSUFBSSxFQUFFLGVBQWU7Z0JBQ3JCLFNBQVM7Z0JBQ1QsU0FBUyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFO2dCQUNuQyxRQUFRO2FBQ1Q7U0FDRixDQUFDLEVBQ0YsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FDakMsQ0FBQztRQUNGLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxrRUFBa0U7SUFDbEUsTUFBTSxDQUFDLFNBQWlCLEVBQUUsTUFBb0M7UUFDNUQsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUM7WUFBRSxPQUFPLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNsRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRSxDQUNsQyxVQUFVLENBQ1IsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFDcEIsY0FBYyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQ3BFLE1BQU0sQ0FDUCxDQUNGLENBQUM7SUFDSixDQUFDO0lBRUQsdURBQXVEO0lBQ3ZELElBQUksQ0FBQyxTQUFpQixFQUFFLE1BQW9DO1FBQzFELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDeEMsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN0QixNQUFNLFVBQVUsQ0FDZCxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUNwQixjQUFjLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsR0FBRyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFDcEUsTUFBTSxDQUNQLENBQUM7WUFDSixDQUFDO1lBQ0QsTUFBTSxVQUFVLENBQ2QsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFDcEIsY0FBYyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUMvRSxNQUFNLENBQ1AsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLE9BQU8sQ0FBQyxTQUFpQixFQUFFLFNBQThCO1FBQy9ELG9CQUFvQixDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN0QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDbkUsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDaEUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3RDLE1BQU0sT0FBTyxHQUFHLEdBQUcsRUFBRTtZQUNuQixJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLE9BQU87Z0JBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDaEYsQ0FBQyxDQUFDO1FBQ0YsS0FBSyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNwQyxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByYW5kb21CeXRlcyB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuaW1wb3J0IHsgYXBwZW5kRmlsZSwgbWtkaXIsIHdyaXRlRmlsZSB9IGZyb20gXCJub2RlOmZzL3Byb21pc2VzXCI7XG5pbXBvcnQgeyB0bXBkaXIgfSBmcm9tIFwibm9kZTpvc1wiO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7XG4gIERlYnVnQ2FwdHVyZUlkU2NoZW1hLFxuICB0eXBlIERlYnVnQ2FwdHVyZUV2ZW50LFxuICB0eXBlIERlYnVnQ2FwdHVyZVNjYWxhcixcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWFwcGtpdC9kZWJ1Z1wiO1xuXG50eXBlIERlYnVnQ2FwdHVyZU1ldGFkYXRhID0gUmVjb3JkPHN0cmluZywgRGVidWdDYXB0dXJlU2NhbGFyPjtcblxuLyoqIERlZmF1bHQgbG9jYWwgZGlyZWN0b3J5IGZvciBicm93c2VyIGRlYnVnIGNhcHR1cmUgSlNPTkwgZmlsZXMuICovXG5leHBvcnQgZnVuY3Rpb24gZGVmYXVsdERlYnVnQ2FwdHVyZURpcmVjdG9yeSgpOiBzdHJpbmcge1xuICByZXR1cm4gcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IFwiZGV2ZWxvcG1lbnRcIlxuICAgID8gam9pbihwcm9jZXNzLmN3ZCgpLCBcIi50bXBcIiwgXCJkZWJ1Zy1jYXB0dXJlc1wiKVxuICAgIDogam9pbih0bXBkaXIoKSwgXCJkYngtdG9vbHMtZGVidWctY2FwdHVyZXNcIik7XG59XG5cbmZ1bmN0aW9uIHNlcmlhbGl6ZUxpbmVzKHJlY29yZHM6IHJlYWRvbmx5IHVua25vd25bXSk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtyZWNvcmRzLm1hcCgocmVjb3JkKSA9PiBKU09OLnN0cmluZ2lmeShyZWNvcmQpKS5qb2luKFwiXFxuXCIpfVxcbmA7XG59XG5cbi8qKiBGaWxlc3lzdGVtLWJhY2tlZCBKU09OTCBzdG9yYWdlIGZvciBBcHBLaXQgYnJvd3NlciBkZWJ1ZyBjYXB0dXJlcy4gKi9cbmV4cG9ydCBjbGFzcyBEZWJ1Z0NhcHR1cmVTdG9yYWdlIHtcbiAgcmVhZG9ubHkgZGlyZWN0b3J5OiBzdHJpbmc7XG4gIHJlYWRvbmx5ICNwZW5kaW5nID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8dm9pZD4+KCk7XG5cbiAgY29uc3RydWN0b3IoZGlyZWN0b3J5ID0gZGVmYXVsdERlYnVnQ2FwdHVyZURpcmVjdG9yeSgpKSB7XG4gICAgdGhpcy5kaXJlY3RvcnkgPSBkaXJlY3Rvcnk7XG4gIH1cblxuICAvKiogUmVzb2x2ZSBhIHZhbGlkYXRlZCBjYXB0dXJlIGlkZW50aWZpZXIgdG8gaXRzIEpTT05MIGZpbGUuICovXG4gIHBhdGgoY2FwdHVyZUlkOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBqb2luKHRoaXMuZGlyZWN0b3J5LCBgJHtEZWJ1Z0NhcHR1cmVJZFNjaGVtYS5wYXJzZShjYXB0dXJlSWQpfS5qc29ubGApO1xuICB9XG5cbiAgLyoqIENyZWF0ZSBhIG5ldyBjYXB0dXJlIGFuZCB3cml0ZSBpdHMgbWV0YWRhdGEgcmVjb3JkLiAqL1xuICBhc3luYyBzdGFydChtZXRhZGF0YTogRGVidWdDYXB0dXJlTWV0YWRhdGEpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGNhcHR1cmVJZCA9IGB2cC0ke0RhdGUubm93KCkudG9TdHJpbmcoMzYpfS0ke3JhbmRvbUJ5dGVzKDQpLnRvU3RyaW5nKFwiaGV4XCIpfWA7XG4gICAgYXdhaXQgbWtkaXIodGhpcy5kaXJlY3RvcnksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIGF3YWl0IHdyaXRlRmlsZShcbiAgICAgIHRoaXMucGF0aChjYXB0dXJlSWQpLFxuICAgICAgc2VyaWFsaXplTGluZXMoW1xuICAgICAgICB7XG4gICAgICAgICAga2luZDogXCJjYXB0dXJlLXN0YXJ0XCIsXG4gICAgICAgICAgY2FwdHVyZUlkLFxuICAgICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgIG1ldGFkYXRhLFxuICAgICAgICB9LFxuICAgICAgXSksXG4gICAgICB7IGVuY29kaW5nOiBcInV0ZjhcIiwgZmxhZzogXCJ3eFwiIH0sXG4gICAgKTtcbiAgICByZXR1cm4gY2FwdHVyZUlkO1xuICB9XG5cbiAgLyoqIEFwcGVuZCBhbiBvcmRlcmVkIGJyb3dzZXIgZXZlbnQgYmF0Y2ggdG8gYW4gYWN0aXZlIGNhcHR1cmUuICovXG4gIGFwcGVuZChjYXB0dXJlSWQ6IHN0cmluZywgZXZlbnRzOiByZWFkb25seSBEZWJ1Z0NhcHR1cmVFdmVudFtdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKGV2ZW50cy5sZW5ndGggPT09IDApIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICByZXR1cm4gdGhpcy5lbnF1ZXVlKGNhcHR1cmVJZCwgKCkgPT5cbiAgICAgIGFwcGVuZEZpbGUoXG4gICAgICAgIHRoaXMucGF0aChjYXB0dXJlSWQpLFxuICAgICAgICBzZXJpYWxpemVMaW5lcyhldmVudHMubWFwKChldmVudCkgPT4gKHsga2luZDogXCJldmVudFwiLCAuLi5ldmVudCB9KSkpLFxuICAgICAgICBcInV0ZjhcIixcbiAgICAgICksXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBBcHBlbmQgZmluYWwgZXZlbnRzIGFuZCBtYXJrIGEgY2FwdHVyZSBjb21wbGV0ZS4gKi9cbiAgc3RvcChjYXB0dXJlSWQ6IHN0cmluZywgZXZlbnRzOiByZWFkb25seSBEZWJ1Z0NhcHR1cmVFdmVudFtdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuZW5xdWV1ZShjYXB0dXJlSWQsIGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChldmVudHMubGVuZ3RoID4gMCkge1xuICAgICAgICBhd2FpdCBhcHBlbmRGaWxlKFxuICAgICAgICAgIHRoaXMucGF0aChjYXB0dXJlSWQpLFxuICAgICAgICAgIHNlcmlhbGl6ZUxpbmVzKGV2ZW50cy5tYXAoKGV2ZW50KSA9PiAoeyBraW5kOiBcImV2ZW50XCIsIC4uLmV2ZW50IH0pKSksXG4gICAgICAgICAgXCJ1dGY4XCIsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBhd2FpdCBhcHBlbmRGaWxlKFxuICAgICAgICB0aGlzLnBhdGgoY2FwdHVyZUlkKSxcbiAgICAgICAgc2VyaWFsaXplTGluZXMoW3sga2luZDogXCJjYXB0dXJlLXN0b3BcIiwgc3RvcHBlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkgfV0pLFxuICAgICAgICBcInV0ZjhcIixcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGVucXVldWUoY2FwdHVyZUlkOiBzdHJpbmcsIG9wZXJhdGlvbjogKCkgPT4gUHJvbWlzZTx2b2lkPik6IFByb21pc2U8dm9pZD4ge1xuICAgIERlYnVnQ2FwdHVyZUlkU2NoZW1hLnBhcnNlKGNhcHR1cmVJZCk7XG4gICAgY29uc3QgcHJldmlvdXMgPSB0aGlzLiNwZW5kaW5nLmdldChjYXB0dXJlSWQpID8/IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIGNvbnN0IGN1cnJlbnQgPSBwcmV2aW91cy5jYXRjaCgoKSA9PiB1bmRlZmluZWQpLnRoZW4ob3BlcmF0aW9uKTtcbiAgICB0aGlzLiNwZW5kaW5nLnNldChjYXB0dXJlSWQsIGN1cnJlbnQpO1xuICAgIGNvbnN0IGNsZWFudXAgPSAoKSA9PiB7XG4gICAgICBpZiAodGhpcy4jcGVuZGluZy5nZXQoY2FwdHVyZUlkKSA9PT0gY3VycmVudCkgdGhpcy4jcGVuZGluZy5kZWxldGUoY2FwdHVyZUlkKTtcbiAgICB9O1xuICAgIHZvaWQgY3VycmVudC50aGVuKGNsZWFudXAsIGNsZWFudXApO1xuICAgIHJldHVybiBjdXJyZW50O1xuICB9XG59XG4iXX0=
@@ -1 +1 @@
1
- {"root":["../src/_auto-configure.ts","../src/appkit.ts","../src/brand-context.ts","../src/cache-storage.ts","../src/databricks.ts","../src/files-cache.ts","../src/identity.ts","../src/interceptor.ts","../src/lakebase-resolver.ts","../src/migration.ts","../src/openapi-tool.ts","../src/plugin-execution.ts","../src/plugin-registry.ts","../src/provision.ts","../src/request-tags.ts","../src/telemetry.ts","../src/tool-operations.ts","../src/tool-provider.ts","../src/toolkit-entries.ts","../index.ts"],"version":"5.9.3"}
1
+ {"root":["../src/_auto-configure.ts","../src/appkit.ts","../src/brand-context.ts","../src/cache-storage.ts","../src/databricks.ts","../src/files-cache.ts","../src/identity.ts","../src/interceptor.ts","../src/lakebase-resolver.ts","../src/migration.ts","../src/openapi-tool.ts","../src/plugin-execution.ts","../src/plugin-registry.ts","../src/provision.ts","../src/request-tags.ts","../src/telemetry.ts","../src/tool-operations.ts","../src/tool-provider.ts","../src/toolkit-entries.ts","../src/debug/plugin.ts","../src/debug/storage.ts","../index.debug.ts","../index.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "devDependencies": {
22
22
  "@databricks/appkit": "0.81.0",
23
- "@dbx-tools/projen": "^0.9.184",
23
+ "@dbx-tools/projen": "^0.9.187",
24
24
  "@types/json-schema": "^7",
25
25
  "@types/node": "^24.6.0",
26
26
  "typescript": "^5.9.3",
@@ -31,13 +31,14 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@databricks/sdk-experimental": "^0.17.0",
34
- "@dbx-tools/auth": "^0.9.184",
35
- "@dbx-tools/cache": "^0.9.184",
36
- "@dbx-tools/core": "^0.9.184",
37
- "@dbx-tools/lakebase": "^0.9.184",
38
- "@dbx-tools/postgres": "^0.9.184",
39
- "@dbx-tools/shared-core": "^0.9.184",
40
- "@dbx-tools/shared-fs": "^0.9.184",
34
+ "@dbx-tools/auth": "^0.9.187",
35
+ "@dbx-tools/cache": "^0.9.187",
36
+ "@dbx-tools/core": "^0.9.187",
37
+ "@dbx-tools/lakebase": "^0.9.187",
38
+ "@dbx-tools/postgres": "^0.9.187",
39
+ "@dbx-tools/shared-appkit": "^0.9.187",
40
+ "@dbx-tools/shared-core": "^0.9.187",
41
+ "@dbx-tools/shared-fs": "^0.9.187",
41
42
  "@opentelemetry/api": "1.9.1",
42
43
  "@opentelemetry/sdk-trace-base": "2.8.0",
43
44
  "zod": "4.3.6"
@@ -53,10 +54,14 @@
53
54
  "types": "./lib/index.d.ts",
54
55
  "default": "./lib/index.js"
55
56
  },
57
+ "./debug": {
58
+ "types": "./lib/index.debug.d.ts",
59
+ "default": "./lib/index.debug.js"
60
+ },
56
61
  "./package.json": "./package.json"
57
62
  }
58
63
  },
59
- "version": "0.9.184",
64
+ "version": "0.9.187",
60
65
  "types": "./lib/index.d.ts",
61
66
  "dbxToolsConfig": {
62
67
  "tags": [
@@ -69,6 +74,10 @@
69
74
  "types": "./lib/index.d.ts",
70
75
  "default": "./lib/index.js"
71
76
  },
77
+ "./debug": {
78
+ "types": "./lib/index.debug.d.ts",
79
+ "default": "./lib/index.debug.js"
80
+ },
72
81
  "./package.json": "./package.json"
73
82
  },
74
83
  "files": [
package/src/appkit.ts CHANGED
@@ -36,11 +36,13 @@ import {
36
36
  // publishes this subpath for exactly that type.
37
37
  import type { PluginMap } from "@databricks/appkit/dist/shared/src/plugin";
38
38
  import { resolveProfile } from "@dbx-tools/auth";
39
+ import { DEBUG_CAPTURE_PLUGIN_NAME } from "@dbx-tools/shared-appkit/debug";
39
40
  import { log, tieAbortSignal } from "@dbx-tools/shared-core";
40
41
 
41
42
  import { resolveAutoConfigurePolicy } from "./_auto-configure.ts";
42
43
  import { loadBrandContext } from "./brand-context.ts";
43
44
  import { createAppKitCacheStorage } from "./cache-storage.ts";
45
+ import { debugCapture } from "./debug/plugin.ts";
44
46
  import { installAsUserDevelopmentPatch } from "./identity.ts";
45
47
  import {
46
48
  createInterceptorContext,
@@ -85,6 +87,9 @@ type AppKitPlugins = NonNullable<AppKitCreateAppConfig["plugins"]>;
85
87
  */
86
88
  export type AutoConfigureMode = "env" | "provision";
87
89
 
90
+ /** Automatic browser debug-capture registration policy. */
91
+ export type DebugCaptureMode = "auto" | boolean;
92
+
88
93
  /** AppKit's `createApp` config plus the dbx-tools auto-configuration switch. */
89
94
  export type CreateAppConfig<T extends AppKitPlugins = AppKitPlugins> = Omit<
90
95
  AppKitCreateAppConfig,
@@ -94,6 +99,11 @@ export type CreateAppConfig<T extends AppKitPlugins = AppKitPlugins> = Omit<
94
99
  onPluginsReady?: (appkit: PluginMap<T>) => void | Promise<void>;
95
100
  /** Auto-configuration to run before AppKit boots. Defaults to `"provision"`. */
96
101
  autoConfigure?: AutoConfigureMode | false;
102
+ /**
103
+ * Register AppKit browser debug-capture routes. `"auto"` (the default)
104
+ * enables them only when `NODE_ENV` is `"development"`.
105
+ */
106
+ debug?: DebugCaptureMode;
97
107
  /**
98
108
  * One or many {@link Interceptor}s handed an {@link InterceptorContext} once
99
109
  * auto-configuration has computed the env. Each receives the resolved env, an
@@ -126,6 +136,16 @@ function pluginNames(config: CreateAppConfig | undefined): string[] {
126
136
  return (config?.plugins ?? []).map((entry) => entry.name);
127
137
  }
128
138
 
139
+ /** Resolve the `createApp.debug` policy for one Node environment. */
140
+ export function debugCaptureEnabled(
141
+ mode: DebugCaptureMode | undefined,
142
+ nodeEnvironment = process.env.NODE_ENV,
143
+ ): boolean {
144
+ if (mode === true) return true;
145
+ if (mode === false) return false;
146
+ return nodeEnvironment === "development";
147
+ }
148
+
129
149
  /**
130
150
  * Run enabled auto-configuration steps without calling AppKit's `createApp`.
131
151
  *
@@ -314,6 +334,7 @@ export async function createApp<T extends AppKitPlugins>(
314
334
 
315
335
  const appConfig = { ...config };
316
336
  delete appConfig.autoConfigure;
337
+ delete appConfig.debug;
317
338
  delete appConfig.interceptor;
318
339
  const onPluginsReady = appConfig.onPluginsReady;
319
340
  appConfig.onPluginsReady = async (app) => {
@@ -334,6 +355,14 @@ export async function createApp<T extends AppKitPlugins>(
334
355
  });
335
356
  }
336
357
 
358
+ if (debugCaptureEnabled(config?.debug) && !usesPlugin(config, DEBUG_CAPTURE_PLUGIN_NAME)) {
359
+ appConfig.plugins = [...(appConfig.plugins ?? []), debugCapture()] as unknown as T;
360
+ logger.debug("createApp: browser debug capture injected", {
361
+ mode: config?.debug ?? "auto",
362
+ nodeEnvironment: process.env.NODE_ENV,
363
+ });
364
+ }
365
+
337
366
  if (interceptors.length === 0) {
338
367
  logger.debug("createApp: no interceptors; delegating to AppKit createApp", {
339
368
  plugins: pluginNames(appConfig),
@@ -0,0 +1,110 @@
1
+ import {
2
+ Plugin,
3
+ toPlugin,
4
+ type BasePluginConfig,
5
+ type IAppRouter,
6
+ type PluginManifest,
7
+ } from "@databricks/appkit";
8
+ import {
9
+ DEBUG_CAPTURE_PLUGIN_NAME,
10
+ DEBUG_CAPTURE_ROUTE,
11
+ DEBUG_CAPTURE_DEFAULT_BASE_PATH,
12
+ DebugCaptureAppendResponseSchema,
13
+ DebugCaptureClientConfigSchema,
14
+ DebugCaptureRequestSchema,
15
+ DebugCaptureStartResponseSchema,
16
+ DebugCaptureStopResponseSchema,
17
+ type DebugCaptureClientConfig,
18
+ } from "@dbx-tools/shared-appkit/debug";
19
+
20
+ import { DebugCaptureStorage } from "./storage.ts";
21
+
22
+ /** Configuration for the AppKit browser debug-capture plugin. */
23
+ export interface DebugCapturePluginConfig extends BasePluginConfig {
24
+ /** Directory where JSONL captures are written. */
25
+ directory?: string;
26
+ }
27
+
28
+ /** Exports available when the debug-capture plugin is registered explicitly. */
29
+ export interface DebugCapturePluginExports {
30
+ /** Directory containing capture JSONL files. */
31
+ directory: string;
32
+ /** Resolve a capture identifier to its JSONL file path. */
33
+ path(captureId: string): string;
34
+ }
35
+
36
+ /** AppKit plugin that receives browser diagnostic event batches. */
37
+ export class DebugCapturePlugin extends Plugin<DebugCapturePluginConfig> {
38
+ static manifest = {
39
+ name: DEBUG_CAPTURE_PLUGIN_NAME,
40
+ displayName: "Browser Debug Capture",
41
+ description: "Records bounded browser, viewport, focus, input, and pointer diagnostics.",
42
+ stability: "beta",
43
+ hidden: true,
44
+ resources: { required: [], optional: [] },
45
+ } satisfies PluginManifest<typeof DEBUG_CAPTURE_PLUGIN_NAME>;
46
+
47
+ readonly #storage: DebugCaptureStorage;
48
+
49
+ constructor(config: DebugCapturePluginConfig = {}) {
50
+ super(config);
51
+ this.#storage = new DebugCaptureStorage(config.directory);
52
+ }
53
+
54
+ private get basePath(): string {
55
+ const endpoint = this.getEndpoints().captures;
56
+ return endpoint?.endsWith(DEBUG_CAPTURE_ROUTE)
57
+ ? endpoint.slice(0, -DEBUG_CAPTURE_ROUTE.length)
58
+ : DEBUG_CAPTURE_DEFAULT_BASE_PATH;
59
+ }
60
+
61
+ override clientConfig(): DebugCaptureClientConfig {
62
+ return DebugCaptureClientConfigSchema.parse({ basePath: this.basePath });
63
+ }
64
+
65
+ override exports(): DebugCapturePluginExports {
66
+ return {
67
+ directory: this.#storage.directory,
68
+ path: (captureId) => this.#storage.path(captureId),
69
+ };
70
+ }
71
+
72
+ override injectRoutes(router: IAppRouter): void {
73
+ this.route(router, {
74
+ name: "captures",
75
+ method: "post",
76
+ path: DEBUG_CAPTURE_ROUTE,
77
+ handler: async (request, response) => {
78
+ response.setHeader("cache-control", "no-store");
79
+ const parsed = DebugCaptureRequestSchema.safeParse(request.body);
80
+ if (!parsed.success) {
81
+ response.status(400).json({ error: "Invalid debug capture request." });
82
+ return;
83
+ }
84
+
85
+ if (parsed.data.action === "start") {
86
+ const captureId = await this.#storage.start({
87
+ ...parsed.data.metadata,
88
+ userAgent: request.header("user-agent")?.slice(0, 500) ?? "unknown",
89
+ });
90
+ response.json(DebugCaptureStartResponseSchema.parse({ captureId }));
91
+ return;
92
+ }
93
+
94
+ if (parsed.data.action === "append") {
95
+ await this.#storage.append(parsed.data.captureId, parsed.data.events);
96
+ response.json(DebugCaptureAppendResponseSchema.parse({ ok: true }));
97
+ return;
98
+ }
99
+
100
+ await this.#storage.stop(parsed.data.captureId, parsed.data.events);
101
+ response.json(
102
+ DebugCaptureStopResponseSchema.parse({ captureId: parsed.data.captureId, ok: true }),
103
+ );
104
+ },
105
+ });
106
+ }
107
+ }
108
+
109
+ /** AppKit registration factory for {@link DebugCapturePlugin}. */
110
+ export const debugCapture = toPlugin(DebugCapturePlugin);
@@ -0,0 +1,98 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { appendFile, mkdir, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import {
6
+ DebugCaptureIdSchema,
7
+ type DebugCaptureEvent,
8
+ type DebugCaptureScalar,
9
+ } from "@dbx-tools/shared-appkit/debug";
10
+
11
+ type DebugCaptureMetadata = Record<string, DebugCaptureScalar>;
12
+
13
+ /** Default local directory for browser debug capture JSONL files. */
14
+ export function defaultDebugCaptureDirectory(): string {
15
+ return process.env.NODE_ENV === "development"
16
+ ? join(process.cwd(), ".tmp", "debug-captures")
17
+ : join(tmpdir(), "dbx-tools-debug-captures");
18
+ }
19
+
20
+ function serializeLines(records: readonly unknown[]): string {
21
+ return `${records.map((record) => JSON.stringify(record)).join("\n")}\n`;
22
+ }
23
+
24
+ /** Filesystem-backed JSONL storage for AppKit browser debug captures. */
25
+ export class DebugCaptureStorage {
26
+ readonly directory: string;
27
+ readonly #pending = new Map<string, Promise<void>>();
28
+
29
+ constructor(directory = defaultDebugCaptureDirectory()) {
30
+ this.directory = directory;
31
+ }
32
+
33
+ /** Resolve a validated capture identifier to its JSONL file. */
34
+ path(captureId: string): string {
35
+ return join(this.directory, `${DebugCaptureIdSchema.parse(captureId)}.jsonl`);
36
+ }
37
+
38
+ /** Create a new capture and write its metadata record. */
39
+ async start(metadata: DebugCaptureMetadata): Promise<string> {
40
+ const captureId = `vp-${Date.now().toString(36)}-${randomBytes(4).toString("hex")}`;
41
+ await mkdir(this.directory, { recursive: true });
42
+ await writeFile(
43
+ this.path(captureId),
44
+ serializeLines([
45
+ {
46
+ kind: "capture-start",
47
+ captureId,
48
+ createdAt: new Date().toISOString(),
49
+ metadata,
50
+ },
51
+ ]),
52
+ { encoding: "utf8", flag: "wx" },
53
+ );
54
+ return captureId;
55
+ }
56
+
57
+ /** Append an ordered browser event batch to an active capture. */
58
+ append(captureId: string, events: readonly DebugCaptureEvent[]): Promise<void> {
59
+ if (events.length === 0) return Promise.resolve();
60
+ return this.enqueue(captureId, () =>
61
+ appendFile(
62
+ this.path(captureId),
63
+ serializeLines(events.map((event) => ({ kind: "event", ...event }))),
64
+ "utf8",
65
+ ),
66
+ );
67
+ }
68
+
69
+ /** Append final events and mark a capture complete. */
70
+ stop(captureId: string, events: readonly DebugCaptureEvent[]): Promise<void> {
71
+ return this.enqueue(captureId, async () => {
72
+ if (events.length > 0) {
73
+ await appendFile(
74
+ this.path(captureId),
75
+ serializeLines(events.map((event) => ({ kind: "event", ...event }))),
76
+ "utf8",
77
+ );
78
+ }
79
+ await appendFile(
80
+ this.path(captureId),
81
+ serializeLines([{ kind: "capture-stop", stoppedAt: new Date().toISOString() }]),
82
+ "utf8",
83
+ );
84
+ });
85
+ }
86
+
87
+ private enqueue(captureId: string, operation: () => Promise<void>): Promise<void> {
88
+ DebugCaptureIdSchema.parse(captureId);
89
+ const previous = this.#pending.get(captureId) ?? Promise.resolve();
90
+ const current = previous.catch(() => undefined).then(operation);
91
+ this.#pending.set(captureId, current);
92
+ const cleanup = () => {
93
+ if (this.#pending.get(captureId) === current) this.#pending.delete(captureId);
94
+ };
95
+ void current.then(cleanup, cleanup);
96
+ return current;
97
+ }
98
+ }