@decaf-ts/integrations 0.3.12 → 0.4.1-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -3
- package/dist/integrations.cjs +445 -7
- package/dist/integrations.js +479 -8
- package/jest.config.cjs +1 -1
- package/lib/cjs/feature-flags/constants.cjs +16 -0
- package/lib/cjs/feature-flags/decorators.cjs +65 -0
- package/lib/cjs/feature-flags/environment.cjs +26 -0
- package/lib/cjs/feature-flags/index.cjs +31 -0
- package/lib/cjs/feature-flags/models/FeatureFlag.model.cjs +81 -0
- package/lib/cjs/feature-flags/models/FeatureFlagAccess.model.cjs +78 -0
- package/lib/cjs/feature-flags/readers/FeatureFlagReader.cjs +25 -0
- package/lib/cjs/feature-flags/readers/index.cjs +19 -0
- package/lib/cjs/feature-flags/services/FeatureFlag.service.cjs +259 -0
- package/lib/cjs/feature-flags/types.cjs +4 -0
- package/lib/cjs/feature-flags/utils.cjs +141 -0
- package/lib/cjs/graph/engine/execution/SwitchGraphNodeExecutor.cjs +9 -9
- package/lib/cjs/graph/shared/nodes/flow-control.cjs +4 -3
- package/lib/cjs/graph/shared/types.cjs +2 -2
- package/lib/cjs/index.cjs +6 -5
- package/lib/cjs/kibana/builders/KibanaIndexBuilder.cjs +329 -0
- package/lib/cjs/kibana/builders/KibanaIndexBuilderCollection.cjs +37 -0
- package/lib/cjs/kibana/builders/index.cjs +20 -0
- package/lib/cjs/kibana/helpers.cjs +20 -16
- package/lib/cjs/kibana/index.cjs +3 -2
- package/lib/cjs/kibana/types.cjs +11 -2
- package/lib/cjs/loader/ObjectLoader.cjs +154 -0
- package/lib/cjs/loader/families.cjs +78 -0
- package/lib/cjs/loader/index.cjs +28 -0
- package/lib/cjs/loader/types.cjs +4 -0
- package/lib/cjs/nest/decorators.cjs +17 -0
- package/lib/cjs/nest/index.cjs +3 -3
- package/lib/cjs/nest/keycloakAuthHandler.cjs +74 -35
- package/lib/cjs/nest/keycloakModule.cjs +7 -10
- package/lib/cjs/nest/types.cjs +2 -2
- package/lib/cjs/nest/utils.cjs +58 -50
- package/lib/cjs/plugins/contract.cjs +76 -0
- package/lib/cjs/plugins/index.cjs +35 -0
- package/lib/cjs/plugins/kibana/host.cjs +24 -0
- package/lib/cjs/plugins/kibana/index.cjs +38 -0
- package/lib/cjs/plugins/kibana/installer.cjs +180 -0
- package/lib/cjs/plugins/kibana/manifest.cjs +33 -0
- package/lib/cjs/plugins/kibana/templates.cjs +503 -0
- package/lib/cjs/plugins/kibana/types.cjs +33 -0
- package/lib/cjs/plugins/superset/host.cjs +26 -0
- package/lib/cjs/plugins/superset/index.cjs +40 -0
- package/lib/cjs/plugins/superset/installer.cjs +232 -0
- package/lib/cjs/plugins/superset/manifest.cjs +35 -0
- package/lib/cjs/plugins/superset/templates.cjs +844 -0
- package/lib/cjs/plugins/superset/types.cjs +39 -0
- package/lib/esm/feature-flags/constants.js +12 -0
- package/lib/esm/feature-flags/decorators.js +49 -0
- package/lib/esm/feature-flags/environment.js +18 -0
- package/lib/esm/feature-flags/index.js +14 -0
- package/lib/esm/feature-flags/models/FeatureFlag.model.js +72 -0
- package/lib/esm/feature-flags/models/FeatureFlagAccess.model.js +69 -0
- package/lib/esm/feature-flags/readers/FeatureFlagReader.js +19 -0
- package/lib/esm/feature-flags/readers/index.js +2 -0
- package/lib/esm/feature-flags/services/FeatureFlag.service.js +250 -0
- package/lib/esm/feature-flags/types.js +2 -0
- package/lib/esm/feature-flags/utils.js +126 -0
- package/lib/esm/graph/engine/execution/SwitchGraphNodeExecutor.js +8 -8
- package/lib/esm/graph/shared/nodes/flow-control.js +3 -2
- package/lib/esm/graph/shared/types.js +1 -1
- package/lib/esm/index.js +5 -4
- package/lib/esm/kibana/builders/KibanaIndexBuilder.js +319 -0
- package/lib/esm/kibana/builders/KibanaIndexBuilderCollection.js +32 -0
- package/lib/esm/kibana/builders/index.js +3 -0
- package/lib/esm/kibana/helpers.js +19 -15
- package/lib/esm/kibana/index.js +2 -1
- package/lib/esm/kibana/types.js +13 -2
- package/lib/esm/loader/ObjectLoader.js +115 -0
- package/lib/esm/loader/families.js +66 -0
- package/lib/esm/loader/index.js +11 -0
- package/lib/esm/loader/types.js +2 -0
- package/lib/esm/nest/decorators.js +12 -0
- package/lib/esm/nest/index.js +2 -2
- package/lib/esm/nest/keycloakAuthHandler.js +67 -35
- package/lib/esm/nest/keycloakModule.js +7 -10
- package/lib/esm/nest/types.js +1 -1
- package/lib/esm/nest/utils.js +55 -46
- package/lib/esm/plugins/contract.js +68 -0
- package/lib/esm/plugins/index.js +18 -0
- package/lib/esm/plugins/kibana/host.js +19 -0
- package/lib/esm/plugins/kibana/index.js +14 -0
- package/lib/esm/plugins/kibana/installer.js +140 -0
- package/lib/esm/plugins/kibana/manifest.js +32 -0
- package/lib/esm/plugins/kibana/templates.js +499 -0
- package/lib/esm/plugins/kibana/types.js +10 -0
- package/lib/esm/plugins/superset/host.js +21 -0
- package/lib/esm/plugins/superset/index.js +16 -0
- package/lib/esm/plugins/superset/installer.js +192 -0
- package/lib/esm/plugins/superset/manifest.js +30 -0
- package/lib/esm/plugins/superset/templates.js +840 -0
- package/lib/esm/plugins/superset/types.js +11 -0
- package/lib/types/feature-flags/constants.d.cts +11 -0
- package/lib/types/feature-flags/constants.d.mts +11 -0
- package/lib/types/feature-flags/decorators.d.cts +11 -0
- package/lib/types/feature-flags/decorators.d.mts +11 -0
- package/lib/types/feature-flags/environment.d.cts +11 -0
- package/lib/types/feature-flags/environment.d.mts +11 -0
- package/lib/types/feature-flags/index.d.cts +13 -0
- package/lib/types/feature-flags/index.d.mts +13 -0
- package/lib/types/feature-flags/models/FeatureFlag.model.d.cts +16 -0
- package/lib/types/feature-flags/models/FeatureFlag.model.d.mts +16 -0
- package/lib/types/feature-flags/models/FeatureFlagAccess.model.d.cts +15 -0
- package/lib/types/feature-flags/models/FeatureFlagAccess.model.d.mts +15 -0
- package/lib/types/feature-flags/readers/FeatureFlagReader.d.cts +10 -0
- package/lib/types/feature-flags/readers/FeatureFlagReader.d.mts +10 -0
- package/lib/types/feature-flags/readers/index.d.cts +1 -0
- package/lib/types/feature-flags/readers/index.d.mts +1 -0
- package/lib/types/feature-flags/services/FeatureFlag.service.d.cts +43 -0
- package/lib/types/feature-flags/services/FeatureFlag.service.d.mts +43 -0
- package/lib/types/feature-flags/types.d.cts +39 -0
- package/lib/types/feature-flags/types.d.mts +39 -0
- package/lib/types/feature-flags/utils.d.cts +13 -0
- package/lib/types/feature-flags/utils.d.mts +13 -0
- package/lib/types/graph/engine/execution/SwitchGraphNodeExecutor.d.cts +2 -2
- package/lib/types/graph/engine/execution/SwitchGraphNodeExecutor.d.mts +2 -2
- package/lib/types/graph/shared/types.d.cts +3 -3
- package/lib/types/graph/shared/types.d.mts +3 -3
- package/lib/types/index.d.cts +3 -2
- package/lib/types/index.d.mts +3 -2
- package/lib/types/kibana/builders/KibanaIndexBuilder.d.cts +67 -0
- package/lib/types/kibana/builders/KibanaIndexBuilder.d.mts +67 -0
- package/lib/types/kibana/builders/KibanaIndexBuilderCollection.d.cts +17 -0
- package/lib/types/kibana/builders/KibanaIndexBuilderCollection.d.mts +17 -0
- package/lib/types/kibana/builders/index.d.cts +2 -0
- package/lib/types/kibana/builders/index.d.mts +2 -0
- package/lib/types/kibana/index.d.cts +1 -0
- package/lib/types/kibana/index.d.mts +1 -0
- package/lib/types/kibana/types.d.cts +11 -0
- package/lib/types/kibana/types.d.mts +11 -0
- package/lib/types/loader/ObjectLoader.d.cts +27 -0
- package/lib/types/loader/ObjectLoader.d.mts +27 -0
- package/lib/types/loader/families.d.cts +34 -0
- package/lib/types/loader/families.d.mts +34 -0
- package/lib/types/loader/index.d.cts +10 -0
- package/lib/types/loader/index.d.mts +10 -0
- package/lib/types/loader/types.d.cts +24 -0
- package/lib/types/loader/types.d.mts +24 -0
- package/lib/types/nest/decorators.d.cts +8 -0
- package/lib/types/nest/decorators.d.mts +8 -0
- package/lib/types/nest/index.d.cts +1 -1
- package/lib/types/nest/index.d.mts +1 -1
- package/lib/types/nest/keycloakAuthHandler.d.cts +19 -42
- package/lib/types/nest/keycloakAuthHandler.d.mts +19 -42
- package/lib/types/nest/keycloakModule.d.cts +3 -5
- package/lib/types/nest/keycloakModule.d.mts +3 -5
- package/lib/types/nest/types.d.cts +2 -0
- package/lib/types/nest/types.d.mts +2 -0
- package/lib/types/nest/utils.d.cts +3 -4
- package/lib/types/nest/utils.d.mts +3 -4
- package/lib/types/plugins/contract.d.cts +180 -0
- package/lib/types/plugins/contract.d.mts +180 -0
- package/lib/types/plugins/index.d.cts +17 -0
- package/lib/types/plugins/index.d.mts +17 -0
- package/lib/types/plugins/kibana/host.d.cts +18 -0
- package/lib/types/plugins/kibana/host.d.mts +18 -0
- package/lib/types/plugins/kibana/index.d.cts +13 -0
- package/lib/types/plugins/kibana/index.d.mts +13 -0
- package/lib/types/plugins/kibana/installer.d.cts +45 -0
- package/lib/types/plugins/kibana/installer.d.mts +45 -0
- package/lib/types/plugins/kibana/manifest.d.cts +31 -0
- package/lib/types/plugins/kibana/manifest.d.mts +31 -0
- package/lib/types/plugins/kibana/templates.d.cts +12 -0
- package/lib/types/plugins/kibana/templates.d.mts +12 -0
- package/lib/types/plugins/kibana/types.d.cts +9 -0
- package/lib/types/plugins/kibana/types.d.mts +9 -0
- package/lib/types/plugins/superset/host.d.cts +20 -0
- package/lib/types/plugins/superset/host.d.mts +20 -0
- package/lib/types/plugins/superset/index.d.cts +15 -0
- package/lib/types/plugins/superset/index.d.mts +15 -0
- package/lib/types/plugins/superset/installer.d.cts +70 -0
- package/lib/types/plugins/superset/installer.d.mts +70 -0
- package/lib/types/plugins/superset/manifest.d.cts +28 -0
- package/lib/types/plugins/superset/manifest.d.mts +28 -0
- package/lib/types/plugins/superset/templates.d.cts +12 -0
- package/lib/types/plugins/superset/templates.d.mts +12 -0
- package/lib/types/plugins/superset/types.d.cts +10 -0
- package/lib/types/plugins/superset/types.d.mts +10 -0
- package/package.json +62 -3
- package/plugins/kibana/.gitignore +16 -0
- package/plugins/kibana/Dockerfile +19 -0
- package/plugins/kibana/docker-compose.yml +50 -0
- package/plugins/kibana/host/index.html +101 -0
- package/plugins/kibana/setup-dashboards.sh +84 -0
- package/plugins/superset/.gitignore +17 -0
- package/plugins/superset/Dockerfile +79 -0
- package/plugins/superset/docker-compose.yml +62 -0
- package/plugins/superset/host/index.html +168 -0
- package/plugins/superset/setup-dashboards.sh +106 -0
- package/plugins/superset/superset_config.py +49 -0
- package/lib/cjs/nest/authService.cjs +0 -91
- package/lib/esm/nest/authService.js +0 -86
- package/lib/types/nest/authService.d.cts +0 -63
- package/lib/types/nest/authService.d.mts +0 -63
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module integrations/plugins/kibana/templates
|
|
3
|
+
* @summary Version-parameterized source templates for the Kibana embed plugin.
|
|
4
|
+
* @description Holds the generated plugin source as string templates. These
|
|
5
|
+
* are materialized onto disk by the installer. The source is the reference
|
|
6
|
+
* multi-tenant embed plugin preserved in DECAF-40 §8. There is never space
|
|
7
|
+
* switching; the plugin is org-agnostic and the current Kibana space comes
|
|
8
|
+
* from the request/session/proxy context.
|
|
9
|
+
*/
|
|
10
|
+
import { KIBANA_APP_ID, KIBANA_PLUGIN_ID, KIBANA_PLUGIN_VERSION } from "./manifest.js";
|
|
11
|
+
const TS_CONFIG = `{
|
|
12
|
+
"extends": "../../tsconfig.json",
|
|
13
|
+
"include": ["public/**/*", "server/**/*"]
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
const PUBLIC_TYPES = `import type {
|
|
17
|
+
AppMountParameters,
|
|
18
|
+
CoreSetup,
|
|
19
|
+
CoreStart,
|
|
20
|
+
Plugin
|
|
21
|
+
} from '@kbn/core/public';
|
|
22
|
+
|
|
23
|
+
import type { DashboardStart } from '@kbn/dashboard-plugin/public';
|
|
24
|
+
import type { EmbeddableStart } from '@kbn/embeddable-plugin/public';
|
|
25
|
+
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
|
26
|
+
|
|
27
|
+
export interface OrgDashboardEmbedSetupDeps {}
|
|
28
|
+
|
|
29
|
+
export interface OrgDashboardEmbedStartDeps {
|
|
30
|
+
dashboard: DashboardStart;
|
|
31
|
+
embeddable: EmbeddableStart;
|
|
32
|
+
data: DataPublicPluginStart;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type OrgDashboardEmbedPlugin = Plugin<
|
|
36
|
+
void,
|
|
37
|
+
void,
|
|
38
|
+
OrgDashboardEmbedSetupDeps,
|
|
39
|
+
OrgDashboardEmbedStartDeps
|
|
40
|
+
>;
|
|
41
|
+
|
|
42
|
+
export interface MountAppArgs {
|
|
43
|
+
coreStart: CoreStart;
|
|
44
|
+
depsStart: OrgDashboardEmbedStartDeps;
|
|
45
|
+
params: AppMountParameters;
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
48
|
+
const PUBLIC_INDEX = `import type { OrgDashboardEmbedPlugin } from './types';
|
|
49
|
+
import { OrgDashboardEmbedPluginImpl } from './plugin';
|
|
50
|
+
|
|
51
|
+
export function plugin(): OrgDashboardEmbedPlugin {
|
|
52
|
+
return new OrgDashboardEmbedPluginImpl();
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
const PUBLIC_PLUGIN = `import React from 'react';
|
|
56
|
+
import ReactDOM from 'react-dom';
|
|
57
|
+
|
|
58
|
+
import type { CoreSetup, CoreStart } from '@kbn/core/public';
|
|
59
|
+
import type {
|
|
60
|
+
OrgDashboardEmbedPlugin,
|
|
61
|
+
OrgDashboardEmbedSetupDeps,
|
|
62
|
+
OrgDashboardEmbedStartDeps
|
|
63
|
+
} from './types';
|
|
64
|
+
|
|
65
|
+
export class OrgDashboardEmbedPluginImpl implements OrgDashboardEmbedPlugin {
|
|
66
|
+
public setup(
|
|
67
|
+
core: CoreSetup<OrgDashboardEmbedStartDeps>,
|
|
68
|
+
deps: OrgDashboardEmbedSetupDeps
|
|
69
|
+
) {
|
|
70
|
+
core.application.register({
|
|
71
|
+
id: '${KIBANA_APP_ID}',
|
|
72
|
+
title: 'Dashboard Embed',
|
|
73
|
+
chromeless: true,
|
|
74
|
+
visibleIn: [],
|
|
75
|
+
async mount(params) {
|
|
76
|
+
const [coreStart, depsStart] = await core.getStartServices();
|
|
77
|
+
const { OrgDashboardEmbedApp } = await import('./application');
|
|
78
|
+
|
|
79
|
+
ReactDOM.render(
|
|
80
|
+
<OrgDashboardEmbedApp
|
|
81
|
+
coreStart={coreStart}
|
|
82
|
+
depsStart={depsStart}
|
|
83
|
+
params={params}
|
|
84
|
+
/>,
|
|
85
|
+
params.element
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
return () => ReactDOM.unmountComponentAtNode(params.element);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public start(core: CoreStart, deps: OrgDashboardEmbedStartDeps) {}
|
|
94
|
+
|
|
95
|
+
public stop() {}
|
|
96
|
+
}
|
|
97
|
+
`;
|
|
98
|
+
const PUBLIC_APPLICATION = `import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
99
|
+
import type { MountAppArgs } from './types';
|
|
100
|
+
|
|
101
|
+
type DashboardQuery = {
|
|
102
|
+
language: 'kuery' | 'lucene';
|
|
103
|
+
query: string;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
type DashboardTimeRange = {
|
|
107
|
+
from: string;
|
|
108
|
+
to: string;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
type SwitchDashboardMessage = {
|
|
112
|
+
type: 'ORG_DASHBOARD_EMBED_SWITCH_DASHBOARD';
|
|
113
|
+
dashboardId: string;
|
|
114
|
+
timeRange?: DashboardTimeRange;
|
|
115
|
+
query?: DashboardQuery;
|
|
116
|
+
filters?: unknown[];
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
type ParentReadyMessage = {
|
|
120
|
+
type: 'ORG_DASHBOARD_EMBED_READY';
|
|
121
|
+
dashboardId: string | null;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
type ParentRenderedMessage = {
|
|
125
|
+
type: 'ORG_DASHBOARD_EMBED_RENDERED';
|
|
126
|
+
dashboardId: string;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
type ParentErrorMessage = {
|
|
130
|
+
type: 'ORG_DASHBOARD_EMBED_ERROR';
|
|
131
|
+
dashboardId: string | null;
|
|
132
|
+
message: string;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
type ParentMessage =
|
|
136
|
+
| ParentReadyMessage
|
|
137
|
+
| ParentRenderedMessage
|
|
138
|
+
| ParentErrorMessage;
|
|
139
|
+
|
|
140
|
+
const DEFAULT_ALLOWED_PARENT_ORIGINS: string[] = [
|
|
141
|
+
window.location.origin
|
|
142
|
+
];
|
|
143
|
+
|
|
144
|
+
function getInitialDashboardId(): string | null {
|
|
145
|
+
const params = new URLSearchParams(window.location.search);
|
|
146
|
+
return params.get('dashboardId');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function getAllowedParentOrigins(): string[] {
|
|
150
|
+
const params = new URLSearchParams(window.location.search);
|
|
151
|
+
const raw = params.get('parentOrigin');
|
|
152
|
+
|
|
153
|
+
if (!raw) {
|
|
154
|
+
return DEFAULT_ALLOWED_PARENT_ORIGINS;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
const decoded = decodeURIComponent(raw);
|
|
159
|
+
const origins = decoded
|
|
160
|
+
.split(',')
|
|
161
|
+
.map((origin) => origin.trim())
|
|
162
|
+
.filter(Boolean);
|
|
163
|
+
|
|
164
|
+
return origins.length > 0 ? origins : DEFAULT_ALLOWED_PARENT_ORIGINS;
|
|
165
|
+
} catch {
|
|
166
|
+
return DEFAULT_ALLOWED_PARENT_ORIGINS;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function isSwitchDashboardMessage(data: unknown): data is SwitchDashboardMessage {
|
|
171
|
+
if (!data || typeof data !== 'object') {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const message = data as Partial<SwitchDashboardMessage>;
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
message.type === 'ORG_DASHBOARD_EMBED_SWITCH_DASHBOARD' &&
|
|
179
|
+
typeof message.dashboardId === 'string' &&
|
|
180
|
+
message.dashboardId.length > 0
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function postToParent(message: ParentMessage, targetOrigin: string) {
|
|
185
|
+
window.parent.postMessage(message, targetOrigin);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function OrgDashboardEmbedApp({
|
|
189
|
+
coreStart,
|
|
190
|
+
depsStart
|
|
191
|
+
}: MountAppArgs) {
|
|
192
|
+
const rootRef = useRef<HTMLDivElement | null>(null);
|
|
193
|
+
const mountedDashboardRef = useRef<any>(null);
|
|
194
|
+
const allowedParentOriginsRef = useRef<string[]>(getAllowedParentOrigins());
|
|
195
|
+
const lastParentOriginRef = useRef<string>(window.location.origin);
|
|
196
|
+
|
|
197
|
+
const [dashboardId, setDashboardId] = useState<string | null>(
|
|
198
|
+
getInitialDashboardId()
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
const [loading, setLoading] = useState(false);
|
|
202
|
+
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
coreStart.chrome.setIsVisible(false);
|
|
205
|
+
}, [coreStart]);
|
|
206
|
+
|
|
207
|
+
const destroyCurrentDashboard = useCallback(() => {
|
|
208
|
+
if (mountedDashboardRef.current?.destroy) {
|
|
209
|
+
mountedDashboardRef.current.destroy();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
mountedDashboardRef.current = null;
|
|
213
|
+
|
|
214
|
+
if (rootRef.current) {
|
|
215
|
+
rootRef.current.innerHTML = '';
|
|
216
|
+
}
|
|
217
|
+
}, []);
|
|
218
|
+
|
|
219
|
+
const applySharedDashboardState = useCallback(
|
|
220
|
+
(message: SwitchDashboardMessage) => {
|
|
221
|
+
if (message.timeRange) {
|
|
222
|
+
depsStart.data.query.timefilter.timefilter.setTime(message.timeRange);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (message.query) {
|
|
226
|
+
depsStart.data.query.queryString.setQuery(message.query);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (message.filters) {
|
|
230
|
+
depsStart.data.query.filterManager.setFilters(message.filters as any);
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
[depsStart.data]
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
useEffect(() => {
|
|
237
|
+
const onMessage = (event: MessageEvent) => {
|
|
238
|
+
if (!allowedParentOriginsRef.current.includes(event.origin)) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (!isSwitchDashboardMessage(event.data)) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
lastParentOriginRef.current = event.origin;
|
|
247
|
+
|
|
248
|
+
applySharedDashboardState(event.data);
|
|
249
|
+
setDashboardId(event.data.dashboardId);
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
window.addEventListener('message', onMessage);
|
|
253
|
+
|
|
254
|
+
postToParent(
|
|
255
|
+
{
|
|
256
|
+
type: 'ORG_DASHBOARD_EMBED_READY',
|
|
257
|
+
dashboardId
|
|
258
|
+
},
|
|
259
|
+
lastParentOriginRef.current
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
return () => window.removeEventListener('message', onMessage);
|
|
263
|
+
}, [applySharedDashboardState, dashboardId]);
|
|
264
|
+
|
|
265
|
+
useEffect(() => {
|
|
266
|
+
if (!dashboardId || !rootRef.current) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
let cancelled = false;
|
|
271
|
+
|
|
272
|
+
async function renderDashboard() {
|
|
273
|
+
setLoading(true);
|
|
274
|
+
|
|
275
|
+
try {
|
|
276
|
+
destroyCurrentDashboard();
|
|
277
|
+
|
|
278
|
+
const factory =
|
|
279
|
+
depsStart.embeddable.getEmbeddableFactory?.('dashboard') ||
|
|
280
|
+
depsStart.embeddable.getEmbeddableFactory?.('dashboard_container');
|
|
281
|
+
|
|
282
|
+
if (!factory) {
|
|
283
|
+
throw new Error('Kibana dashboard embeddable factory was not found.');
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const embeddable = await factory.create({
|
|
287
|
+
id: dashboardId,
|
|
288
|
+
savedObjectId: dashboardId,
|
|
289
|
+
viewMode: 'view',
|
|
290
|
+
hidePanelTitles: false,
|
|
291
|
+
useMargins: true,
|
|
292
|
+
syncColors: true,
|
|
293
|
+
syncCursor: true,
|
|
294
|
+
syncTooltips: true,
|
|
295
|
+
timeRange: depsStart.data.query.timefilter.timefilter.getTime(),
|
|
296
|
+
query: depsStart.data.query.queryString.getQuery(),
|
|
297
|
+
filters: depsStart.data.query.filterManager.getFilters()
|
|
298
|
+
} as any);
|
|
299
|
+
|
|
300
|
+
if (cancelled) {
|
|
301
|
+
embeddable.destroy?.();
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
embeddable.render(rootRef.current!);
|
|
306
|
+
mountedDashboardRef.current = embeddable;
|
|
307
|
+
|
|
308
|
+
postToParent(
|
|
309
|
+
{
|
|
310
|
+
type: 'ORG_DASHBOARD_EMBED_RENDERED',
|
|
311
|
+
dashboardId
|
|
312
|
+
},
|
|
313
|
+
lastParentOriginRef.current
|
|
314
|
+
);
|
|
315
|
+
} catch (error) {
|
|
316
|
+
const message =
|
|
317
|
+
error instanceof Error ? error.message : 'Unknown dashboard error';
|
|
318
|
+
|
|
319
|
+
if (rootRef.current) {
|
|
320
|
+
rootRef.current.innerHTML = \`
|
|
321
|
+
<div style="
|
|
322
|
+
padding: 24px;
|
|
323
|
+
font-family: sans-serif;
|
|
324
|
+
color: #bd271e;
|
|
325
|
+
">
|
|
326
|
+
Failed to render dashboard: \${message}
|
|
327
|
+
</div>
|
|
328
|
+
\`;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
postToParent(
|
|
332
|
+
{
|
|
333
|
+
type: 'ORG_DASHBOARD_EMBED_ERROR',
|
|
334
|
+
dashboardId,
|
|
335
|
+
message
|
|
336
|
+
},
|
|
337
|
+
lastParentOriginRef.current
|
|
338
|
+
);
|
|
339
|
+
} finally {
|
|
340
|
+
if (!cancelled) {
|
|
341
|
+
setLoading(false);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
renderDashboard();
|
|
347
|
+
|
|
348
|
+
return () => {
|
|
349
|
+
cancelled = true;
|
|
350
|
+
};
|
|
351
|
+
}, [dashboardId, depsStart, destroyCurrentDashboard]);
|
|
352
|
+
|
|
353
|
+
useEffect(() => {
|
|
354
|
+
return () => {
|
|
355
|
+
destroyCurrentDashboard();
|
|
356
|
+
};
|
|
357
|
+
}, [destroyCurrentDashboard]);
|
|
358
|
+
|
|
359
|
+
return (
|
|
360
|
+
<div
|
|
361
|
+
style={{
|
|
362
|
+
position: 'fixed',
|
|
363
|
+
inset: 0,
|
|
364
|
+
width: '100vw',
|
|
365
|
+
height: '100vh',
|
|
366
|
+
overflow: 'hidden',
|
|
367
|
+
background: '#fff'
|
|
368
|
+
}}
|
|
369
|
+
>
|
|
370
|
+
{loading && (
|
|
371
|
+
<div
|
|
372
|
+
style={{
|
|
373
|
+
position: 'absolute',
|
|
374
|
+
inset: 0,
|
|
375
|
+
zIndex: 10,
|
|
376
|
+
display: 'flex',
|
|
377
|
+
alignItems: 'center',
|
|
378
|
+
justifyContent: 'center',
|
|
379
|
+
fontFamily: 'sans-serif',
|
|
380
|
+
background: '#fff'
|
|
381
|
+
}}
|
|
382
|
+
>
|
|
383
|
+
Loading dashboard…
|
|
384
|
+
</div>
|
|
385
|
+
)}
|
|
386
|
+
|
|
387
|
+
<div
|
|
388
|
+
ref={rootRef}
|
|
389
|
+
style={{
|
|
390
|
+
position: 'absolute',
|
|
391
|
+
inset: 0,
|
|
392
|
+
width: '100%',
|
|
393
|
+
height: '100%'
|
|
394
|
+
}}
|
|
395
|
+
/>
|
|
396
|
+
</div>
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
`;
|
|
400
|
+
const SERVER_INDEX = `import type { PluginInitializerContext } from '@kbn/core/server';
|
|
401
|
+
import { OrgDashboardEmbedServerPlugin } from './plugin';
|
|
402
|
+
|
|
403
|
+
export function plugin(initializerContext: PluginInitializerContext) {
|
|
404
|
+
return new OrgDashboardEmbedServerPlugin(initializerContext);
|
|
405
|
+
}
|
|
406
|
+
`;
|
|
407
|
+
const SERVER_PLUGIN = `import type {
|
|
408
|
+
CoreSetup,
|
|
409
|
+
CoreStart,
|
|
410
|
+
Plugin,
|
|
411
|
+
PluginInitializerContext
|
|
412
|
+
} from '@kbn/core/server';
|
|
413
|
+
|
|
414
|
+
export class OrgDashboardEmbedServerPlugin implements Plugin {
|
|
415
|
+
constructor(private readonly initializerContext: PluginInitializerContext) {}
|
|
416
|
+
|
|
417
|
+
public setup(core: CoreSetup) {
|
|
418
|
+
const router = core.http.createRouter();
|
|
419
|
+
|
|
420
|
+
router.get(
|
|
421
|
+
{
|
|
422
|
+
path: '/api/${KIBANA_APP_ID}/health',
|
|
423
|
+
validate: false
|
|
424
|
+
},
|
|
425
|
+
async (context, request, response) => {
|
|
426
|
+
return response.ok({
|
|
427
|
+
body: {
|
|
428
|
+
ok: true,
|
|
429
|
+
plugin: '${KIBANA_APP_ID}'
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
public start(core: CoreStart) {}
|
|
437
|
+
|
|
438
|
+
public stop() {}
|
|
439
|
+
}
|
|
440
|
+
`;
|
|
441
|
+
const README = `# ${KIBANA_PLUGIN_ID}
|
|
442
|
+
|
|
443
|
+
Multi-tenant, org-agnostic Kibana dashboard embed plugin.
|
|
444
|
+
|
|
445
|
+
There is never space switching. Each org already lands in its own Kibana space
|
|
446
|
+
through the backend proxy/session URL, and the plugin only switches dashboards
|
|
447
|
+
within the current space.
|
|
448
|
+
|
|
449
|
+
## Build
|
|
450
|
+
|
|
451
|
+
Kibana plugins must match the exact Kibana version and must be built within the
|
|
452
|
+
Kibana repo (see kbn-plugin-generator). Place this directory under
|
|
453
|
+
\`kibana-extra/\` (or \`plugins/\`) and run the Kibana plugin build, e.g.:
|
|
454
|
+
|
|
455
|
+
\`\`\`
|
|
456
|
+
yarn build
|
|
457
|
+
\`\`\`
|
|
458
|
+
|
|
459
|
+
## Embed URL
|
|
460
|
+
|
|
461
|
+
\`\`\`
|
|
462
|
+
/kibana/app/${KIBANA_APP_ID}?dashboardId=<id>&parentOrigin=<origin>
|
|
463
|
+
\`\`\`
|
|
464
|
+
|
|
465
|
+
## Message protocol
|
|
466
|
+
|
|
467
|
+
- Parent -> plugin: \`ORG_DASHBOARD_EMBED_SWITCH_DASHBOARD\`
|
|
468
|
+
- Plugin -> parent: \`ORG_DASHBOARD_EMBED_READY\` / \`ORG_DASHBOARD_EMBED_RENDERED\` / \`ORG_DASHBOARD_EMBED_ERROR\`
|
|
469
|
+
|
|
470
|
+
Version: ${KIBANA_PLUGIN_VERSION}
|
|
471
|
+
`;
|
|
472
|
+
/**
|
|
473
|
+
* Returns the full set of generated plugin files for a target Kibana version.
|
|
474
|
+
*
|
|
475
|
+
* @param targetVersion - Kibana version baked into `kibana.json`.
|
|
476
|
+
*/
|
|
477
|
+
export function kibanaPluginFiles(targetVersion) {
|
|
478
|
+
const manifest = JSON.stringify({
|
|
479
|
+
id: KIBANA_PLUGIN_ID,
|
|
480
|
+
version: KIBANA_PLUGIN_VERSION,
|
|
481
|
+
kibanaVersion: targetVersion,
|
|
482
|
+
server: true,
|
|
483
|
+
ui: true,
|
|
484
|
+
requiredPlugins: ["dashboard", "embeddable", "data"],
|
|
485
|
+
optionalPlugins: [],
|
|
486
|
+
}, null, 2);
|
|
487
|
+
return [
|
|
488
|
+
{ path: "kibana.json", content: `${manifest}\n` },
|
|
489
|
+
{ path: "tsconfig.json", content: `${TS_CONFIG}\n` },
|
|
490
|
+
{ path: "README.md", content: README },
|
|
491
|
+
{ path: "public/types.ts", content: PUBLIC_TYPES },
|
|
492
|
+
{ path: "public/index.ts", content: PUBLIC_INDEX },
|
|
493
|
+
{ path: "public/plugin.tsx", content: PUBLIC_PLUGIN },
|
|
494
|
+
{ path: "public/application.tsx", content: PUBLIC_APPLICATION },
|
|
495
|
+
{ path: "server/index.ts", content: SERVER_INDEX },
|
|
496
|
+
{ path: "server/plugin.ts", content: SERVER_PLUGIN },
|
|
497
|
+
];
|
|
498
|
+
}
|
|
499
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVtcGxhdGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3BsdWdpbnMva2liYW5hL3RlbXBsYXRlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7R0FRRztBQUNILE9BQU8sRUFBRSxhQUFhLEVBQUUsZ0JBQWdCLEVBQUUscUJBQXFCLEVBQUUsc0JBQW1CO0FBU3BGLE1BQU0sU0FBUyxHQUFHOzs7O0NBSWpCLENBQUM7QUFFRixNQUFNLFlBQVksR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQStCcEIsQ0FBQztBQUVGLE1BQU0sWUFBWSxHQUFHOzs7Ozs7Q0FNcEIsQ0FBQztBQUVGLE1BQU0sYUFBYSxHQUFHOzs7Ozs7Ozs7Ozs7Ozs7O2FBZ0JULGFBQWE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBMEJ6QixDQUFDO0FBRUYsTUFBTSxrQkFBa0IsR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQTZTMUIsQ0FBQztBQUVGLE1BQU0sWUFBWSxHQUFHOzs7Ozs7Q0FNcEIsQ0FBQztBQUVGLE1BQU0sYUFBYSxHQUFHOzs7Ozs7Ozs7Ozs7Ozs7c0JBZUEsYUFBYTs7Ozs7Ozt1QkFPWixhQUFhOzs7Ozs7Ozs7OztDQVduQyxDQUFDO0FBRUYsTUFBTSxNQUFNLEdBQUcsS0FBSyxnQkFBZ0I7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztjQXFCdEIsYUFBYTs7Ozs7Ozs7V0FRaEIscUJBQXFCO0NBQy9CLENBQUM7QUFFRjs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUFDLGFBQXFCO0lBQ3JELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQzdCO1FBQ0UsRUFBRSxFQUFFLGdCQUFnQjtRQUNwQixPQUFPLEVBQUUscUJBQXFCO1FBQzlCLGFBQWEsRUFBRSxhQUFhO1FBQzVCLE1BQU0sRUFBRSxJQUFJO1FBQ1osRUFBRSxFQUFFLElBQUk7UUFDUixlQUFlLEVBQUUsQ0FBQyxXQUFXLEVBQUUsWUFBWSxFQUFFLE1BQU0sQ0FBQztRQUNwRCxlQUFlLEVBQUUsRUFBRTtLQUNwQixFQUNELElBQUksRUFDSixDQUFDLENBQ0YsQ0FBQztJQUVGLE9BQU87UUFDTCxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLEdBQUcsUUFBUSxJQUFJLEVBQUU7UUFDakQsRUFBRSxJQUFJLEVBQUUsZUFBZSxFQUFFLE9BQU8sRUFBRSxHQUFHLFNBQVMsSUFBSSxFQUFFO1FBQ3BELEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFO1FBQ3RDLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUU7UUFDbEQsRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRTtRQUNsRCxFQUFFLElBQUksRUFBRSxtQkFBbUIsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFO1FBQ3JELEVBQUUsSUFBSSxFQUFFLHdCQUF3QixFQUFFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRTtRQUMvRCxFQUFFLElBQUksRUFBRSxpQkFBaUIsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFO1FBQ2xELEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUU7S0FDckQsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBtb2R1bGUgaW50ZWdyYXRpb25zL3BsdWdpbnMva2liYW5hL3RlbXBsYXRlc1xuICogQHN1bW1hcnkgVmVyc2lvbi1wYXJhbWV0ZXJpemVkIHNvdXJjZSB0ZW1wbGF0ZXMgZm9yIHRoZSBLaWJhbmEgZW1iZWQgcGx1Z2luLlxuICogQGRlc2NyaXB0aW9uIEhvbGRzIHRoZSBnZW5lcmF0ZWQgcGx1Z2luIHNvdXJjZSBhcyBzdHJpbmcgdGVtcGxhdGVzLiBUaGVzZVxuICogYXJlIG1hdGVyaWFsaXplZCBvbnRvIGRpc2sgYnkgdGhlIGluc3RhbGxlci4gVGhlIHNvdXJjZSBpcyB0aGUgcmVmZXJlbmNlXG4gKiBtdWx0aS10ZW5hbnQgZW1iZWQgcGx1Z2luIHByZXNlcnZlZCBpbiBERUNBRi00MCDCpzguIFRoZXJlIGlzIG5ldmVyIHNwYWNlXG4gKiBzd2l0Y2hpbmc7IHRoZSBwbHVnaW4gaXMgb3JnLWFnbm9zdGljIGFuZCB0aGUgY3VycmVudCBLaWJhbmEgc3BhY2UgY29tZXNcbiAqIGZyb20gdGhlIHJlcXVlc3Qvc2Vzc2lvbi9wcm94eSBjb250ZXh0LlxuICovXG5pbXBvcnQgeyBLSUJBTkFfQVBQX0lELCBLSUJBTkFfUExVR0lOX0lELCBLSUJBTkFfUExVR0lOX1ZFUlNJT04gfSBmcm9tIFwiLi9tYW5pZmVzdFwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEtpYmFuYVBsdWdpbkZpbGUge1xuICAvKiogUmVsYXRpdmUgcGF0aCB3aXRoaW4gdGhlIHBsdWdpbiBkaXJlY3RvcnkuICovXG4gIHBhdGg6IHN0cmluZztcbiAgLyoqIEZpbGUgY29udGVudHMuICovXG4gIGNvbnRlbnQ6IHN0cmluZztcbn1cblxuY29uc3QgVFNfQ09ORklHID0gYHtcbiAgXCJleHRlbmRzXCI6IFwiLi4vLi4vdHNjb25maWcuanNvblwiLFxuICBcImluY2x1ZGVcIjogW1wicHVibGljLyoqLypcIiwgXCJzZXJ2ZXIvKiovKlwiXVxufVxuYDtcblxuY29uc3QgUFVCTElDX1RZUEVTID0gYGltcG9ydCB0eXBlIHtcbiAgQXBwTW91bnRQYXJhbWV0ZXJzLFxuICBDb3JlU2V0dXAsXG4gIENvcmVTdGFydCxcbiAgUGx1Z2luXG59IGZyb20gJ0BrYm4vY29yZS9wdWJsaWMnO1xuXG5pbXBvcnQgdHlwZSB7IERhc2hib2FyZFN0YXJ0IH0gZnJvbSAnQGtibi9kYXNoYm9hcmQtcGx1Z2luL3B1YmxpYyc7XG5pbXBvcnQgdHlwZSB7IEVtYmVkZGFibGVTdGFydCB9IGZyb20gJ0BrYm4vZW1iZWRkYWJsZS1wbHVnaW4vcHVibGljJztcbmltcG9ydCB0eXBlIHsgRGF0YVB1YmxpY1BsdWdpblN0YXJ0IH0gZnJvbSAnQGtibi9kYXRhLXBsdWdpbi9wdWJsaWMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9yZ0Rhc2hib2FyZEVtYmVkU2V0dXBEZXBzIHt9XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3JnRGFzaGJvYXJkRW1iZWRTdGFydERlcHMge1xuICBkYXNoYm9hcmQ6IERhc2hib2FyZFN0YXJ0O1xuICBlbWJlZGRhYmxlOiBFbWJlZGRhYmxlU3RhcnQ7XG4gIGRhdGE6IERhdGFQdWJsaWNQbHVnaW5TdGFydDtcbn1cblxuZXhwb3J0IHR5cGUgT3JnRGFzaGJvYXJkRW1iZWRQbHVnaW4gPSBQbHVnaW48XG4gIHZvaWQsXG4gIHZvaWQsXG4gIE9yZ0Rhc2hib2FyZEVtYmVkU2V0dXBEZXBzLFxuICBPcmdEYXNoYm9hcmRFbWJlZFN0YXJ0RGVwc1xuPjtcblxuZXhwb3J0IGludGVyZmFjZSBNb3VudEFwcEFyZ3Mge1xuICBjb3JlU3RhcnQ6IENvcmVTdGFydDtcbiAgZGVwc1N0YXJ0OiBPcmdEYXNoYm9hcmRFbWJlZFN0YXJ0RGVwcztcbiAgcGFyYW1zOiBBcHBNb3VudFBhcmFtZXRlcnM7XG59XG5gO1xuXG5jb25zdCBQVUJMSUNfSU5ERVggPSBgaW1wb3J0IHR5cGUgeyBPcmdEYXNoYm9hcmRFbWJlZFBsdWdpbiB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgT3JnRGFzaGJvYXJkRW1iZWRQbHVnaW5JbXBsIH0gZnJvbSAnLi9wbHVnaW4nO1xuXG5leHBvcnQgZnVuY3Rpb24gcGx1Z2luKCk6IE9yZ0Rhc2hib2FyZEVtYmVkUGx1Z2luIHtcbiAgcmV0dXJuIG5ldyBPcmdEYXNoYm9hcmRFbWJlZFBsdWdpbkltcGwoKTtcbn1cbmA7XG5cbmNvbnN0IFBVQkxJQ19QTFVHSU4gPSBgaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCBSZWFjdERPTSBmcm9tICdyZWFjdC1kb20nO1xuXG5pbXBvcnQgdHlwZSB7IENvcmVTZXR1cCwgQ29yZVN0YXJ0IH0gZnJvbSAnQGtibi9jb3JlL3B1YmxpYyc7XG5pbXBvcnQgdHlwZSB7XG4gIE9yZ0Rhc2hib2FyZEVtYmVkUGx1Z2luLFxuICBPcmdEYXNoYm9hcmRFbWJlZFNldHVwRGVwcyxcbiAgT3JnRGFzaGJvYXJkRW1iZWRTdGFydERlcHNcbn0gZnJvbSAnLi90eXBlcyc7XG5cbmV4cG9ydCBjbGFzcyBPcmdEYXNoYm9hcmRFbWJlZFBsdWdpbkltcGwgaW1wbGVtZW50cyBPcmdEYXNoYm9hcmRFbWJlZFBsdWdpbiB7XG4gIHB1YmxpYyBzZXR1cChcbiAgICBjb3JlOiBDb3JlU2V0dXA8T3JnRGFzaGJvYXJkRW1iZWRTdGFydERlcHM+LFxuICAgIGRlcHM6IE9yZ0Rhc2hib2FyZEVtYmVkU2V0dXBEZXBzXG4gICkge1xuICAgIGNvcmUuYXBwbGljYXRpb24ucmVnaXN0ZXIoe1xuICAgICAgaWQ6ICcke0tJQkFOQV9BUFBfSUR9JyxcbiAgICAgIHRpdGxlOiAnRGFzaGJvYXJkIEVtYmVkJyxcbiAgICAgIGNocm9tZWxlc3M6IHRydWUsXG4gICAgICB2aXNpYmxlSW46IFtdLFxuICAgICAgYXN5bmMgbW91bnQocGFyYW1zKSB7XG4gICAgICAgIGNvbnN0IFtjb3JlU3RhcnQsIGRlcHNTdGFydF0gPSBhd2FpdCBjb3JlLmdldFN0YXJ0U2VydmljZXMoKTtcbiAgICAgICAgY29uc3QgeyBPcmdEYXNoYm9hcmRFbWJlZEFwcCB9ID0gYXdhaXQgaW1wb3J0KCcuL2FwcGxpY2F0aW9uJyk7XG5cbiAgICAgICAgUmVhY3RET00ucmVuZGVyKFxuICAgICAgICAgIDxPcmdEYXNoYm9hcmRFbWJlZEFwcFxuICAgICAgICAgICAgY29yZVN0YXJ0PXtjb3JlU3RhcnR9XG4gICAgICAgICAgICBkZXBzU3RhcnQ9e2RlcHNTdGFydH1cbiAgICAgICAgICAgIHBhcmFtcz17cGFyYW1zfVxuICAgICAgICAgIC8+LFxuICAgICAgICAgIHBhcmFtcy5lbGVtZW50XG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuICgpID0+IFJlYWN0RE9NLnVubW91bnRDb21wb25lbnRBdE5vZGUocGFyYW1zLmVsZW1lbnQpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHN0YXJ0KGNvcmU6IENvcmVTdGFydCwgZGVwczogT3JnRGFzaGJvYXJkRW1iZWRTdGFydERlcHMpIHt9XG5cbiAgcHVibGljIHN0b3AoKSB7fVxufVxuYDtcblxuY29uc3QgUFVCTElDX0FQUExJQ0FUSU9OID0gYGltcG9ydCBSZWFjdCwgeyB1c2VDYWxsYmFjaywgdXNlRWZmZWN0LCB1c2VSZWYsIHVzZVN0YXRlIH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0IHR5cGUgeyBNb3VudEFwcEFyZ3MgfSBmcm9tICcuL3R5cGVzJztcblxudHlwZSBEYXNoYm9hcmRRdWVyeSA9IHtcbiAgbGFuZ3VhZ2U6ICdrdWVyeScgfCAnbHVjZW5lJztcbiAgcXVlcnk6IHN0cmluZztcbn07XG5cbnR5cGUgRGFzaGJvYXJkVGltZVJhbmdlID0ge1xuICBmcm9tOiBzdHJpbmc7XG4gIHRvOiBzdHJpbmc7XG59O1xuXG50eXBlIFN3aXRjaERhc2hib2FyZE1lc3NhZ2UgPSB7XG4gIHR5cGU6ICdPUkdfREFTSEJPQVJEX0VNQkVEX1NXSVRDSF9EQVNIQk9BUkQnO1xuICBkYXNoYm9hcmRJZDogc3RyaW5nO1xuICB0aW1lUmFuZ2U/OiBEYXNoYm9hcmRUaW1lUmFuZ2U7XG4gIHF1ZXJ5PzogRGFzaGJvYXJkUXVlcnk7XG4gIGZpbHRlcnM/OiB1bmtub3duW107XG59O1xuXG50eXBlIFBhcmVudFJlYWR5TWVzc2FnZSA9IHtcbiAgdHlwZTogJ09SR19EQVNIQk9BUkRfRU1CRURfUkVBRFknO1xuICBkYXNoYm9hcmRJZDogc3RyaW5nIHwgbnVsbDtcbn07XG5cbnR5cGUgUGFyZW50UmVuZGVyZWRNZXNzYWdlID0ge1xuICB0eXBlOiAnT1JHX0RBU0hCT0FSRF9FTUJFRF9SRU5ERVJFRCc7XG4gIGRhc2hib2FyZElkOiBzdHJpbmc7XG59O1xuXG50eXBlIFBhcmVudEVycm9yTWVzc2FnZSA9IHtcbiAgdHlwZTogJ09SR19EQVNIQk9BUkRfRU1CRURfRVJST1InO1xuICBkYXNoYm9hcmRJZDogc3RyaW5nIHwgbnVsbDtcbiAgbWVzc2FnZTogc3RyaW5nO1xufTtcblxudHlwZSBQYXJlbnRNZXNzYWdlID1cbiAgfCBQYXJlbnRSZWFkeU1lc3NhZ2VcbiAgfCBQYXJlbnRSZW5kZXJlZE1lc3NhZ2VcbiAgfCBQYXJlbnRFcnJvck1lc3NhZ2U7XG5cbmNvbnN0IERFRkFVTFRfQUxMT1dFRF9QQVJFTlRfT1JJR0lOUzogc3RyaW5nW10gPSBbXG4gIHdpbmRvdy5sb2NhdGlvbi5vcmlnaW5cbl07XG5cbmZ1bmN0aW9uIGdldEluaXRpYWxEYXNoYm9hcmRJZCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgY29uc3QgcGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoKTtcbiAgcmV0dXJuIHBhcmFtcy5nZXQoJ2Rhc2hib2FyZElkJyk7XG59XG5cbmZ1bmN0aW9uIGdldEFsbG93ZWRQYXJlbnRPcmlnaW5zKCk6IHN0cmluZ1tdIHtcbiAgY29uc3QgcGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoKTtcbiAgY29uc3QgcmF3ID0gcGFyYW1zLmdldCgncGFyZW50T3JpZ2luJyk7XG5cbiAgaWYgKCFyYXcpIHtcbiAgICByZXR1cm4gREVGQVVMVF9BTExPV0VEX1BBUkVOVF9PUklHSU5TO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBkZWNvZGVkID0gZGVjb2RlVVJJQ29tcG9uZW50KHJhdyk7XG4gICAgY29uc3Qgb3JpZ2lucyA9IGRlY29kZWRcbiAgICAgIC5zcGxpdCgnLCcpXG4gICAgICAubWFwKChvcmlnaW4pID0+IG9yaWdpbi50cmltKCkpXG4gICAgICAuZmlsdGVyKEJvb2xlYW4pO1xuXG4gICAgcmV0dXJuIG9yaWdpbnMubGVuZ3RoID4gMCA/IG9yaWdpbnMgOiBERUZBVUxUX0FMTE9XRURfUEFSRU5UX09SSUdJTlM7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBERUZBVUxUX0FMTE9XRURfUEFSRU5UX09SSUdJTlM7XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNTd2l0Y2hEYXNoYm9hcmRNZXNzYWdlKGRhdGE6IHVua25vd24pOiBkYXRhIGlzIFN3aXRjaERhc2hib2FyZE1lc3NhZ2Uge1xuICBpZiAoIWRhdGEgfHwgdHlwZW9mIGRhdGEgIT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgbWVzc2FnZSA9IGRhdGEgYXMgUGFydGlhbDxTd2l0Y2hEYXNoYm9hcmRNZXNzYWdlPjtcblxuICByZXR1cm4gKFxuICAgIG1lc3NhZ2UudHlwZSA9PT0gJ09SR19EQVNIQk9BUkRfRU1CRURfU1dJVENIX0RBU0hCT0FSRCcgJiZcbiAgICB0eXBlb2YgbWVzc2FnZS5kYXNoYm9hcmRJZCA9PT0gJ3N0cmluZycgJiZcbiAgICBtZXNzYWdlLmRhc2hib2FyZElkLmxlbmd0aCA+IDBcbiAgKTtcbn1cblxuZnVuY3Rpb24gcG9zdFRvUGFyZW50KG1lc3NhZ2U6IFBhcmVudE1lc3NhZ2UsIHRhcmdldE9yaWdpbjogc3RyaW5nKSB7XG4gIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UobWVzc2FnZSwgdGFyZ2V0T3JpZ2luKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIE9yZ0Rhc2hib2FyZEVtYmVkQXBwKHtcbiAgY29yZVN0YXJ0LFxuICBkZXBzU3RhcnRcbn06IE1vdW50QXBwQXJncykge1xuICBjb25zdCByb290UmVmID0gdXNlUmVmPEhUTUxEaXZFbGVtZW50IHwgbnVsbD4obnVsbCk7XG4gIGNvbnN0IG1vdW50ZWREYXNoYm9hcmRSZWYgPSB1c2VSZWY8YW55PihudWxsKTtcbiAgY29uc3QgYWxsb3dlZFBhcmVudE9yaWdpbnNSZWYgPSB1c2VSZWY8c3RyaW5nW10+KGdldEFsbG93ZWRQYXJlbnRPcmlnaW5zKCkpO1xuICBjb25zdCBsYXN0UGFyZW50T3JpZ2luUmVmID0gdXNlUmVmPHN0cmluZz4od2luZG93LmxvY2F0aW9uLm9yaWdpbik7XG5cbiAgY29uc3QgW2Rhc2hib2FyZElkLCBzZXREYXNoYm9hcmRJZF0gPSB1c2VTdGF0ZTxzdHJpbmcgfCBudWxsPihcbiAgICBnZXRJbml0aWFsRGFzaGJvYXJkSWQoKVxuICApO1xuXG4gIGNvbnN0IFtsb2FkaW5nLCBzZXRMb2FkaW5nXSA9IHVzZVN0YXRlKGZhbHNlKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGNvcmVTdGFydC5jaHJvbWUuc2V0SXNWaXNpYmxlKGZhbHNlKTtcbiAgfSwgW2NvcmVTdGFydF0pO1xuXG4gIGNvbnN0IGRlc3Ryb3lDdXJyZW50RGFzaGJvYXJkID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChtb3VudGVkRGFzaGJvYXJkUmVmLmN1cnJlbnQ/LmRlc3Ryb3kpIHtcbiAgICAgIG1vdW50ZWREYXNoYm9hcmRSZWYuY3VycmVudC5kZXN0cm95KCk7XG4gICAgfVxuXG4gICAgbW91bnRlZERhc2hib2FyZFJlZi5jdXJyZW50ID0gbnVsbDtcblxuICAgIGlmIChyb290UmVmLmN1cnJlbnQpIHtcbiAgICAgIHJvb3RSZWYuY3VycmVudC5pbm5lckhUTUwgPSAnJztcbiAgICB9XG4gIH0sIFtdKTtcblxuICBjb25zdCBhcHBseVNoYXJlZERhc2hib2FyZFN0YXRlID0gdXNlQ2FsbGJhY2soXG4gICAgKG1lc3NhZ2U6IFN3aXRjaERhc2hib2FyZE1lc3NhZ2UpID0+IHtcbiAgICAgIGlmIChtZXNzYWdlLnRpbWVSYW5nZSkge1xuICAgICAgICBkZXBzU3RhcnQuZGF0YS5xdWVyeS50aW1lZmlsdGVyLnRpbWVmaWx0ZXIuc2V0VGltZShtZXNzYWdlLnRpbWVSYW5nZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChtZXNzYWdlLnF1ZXJ5KSB7XG4gICAgICAgIGRlcHNTdGFydC5kYXRhLnF1ZXJ5LnF1ZXJ5U3RyaW5nLnNldFF1ZXJ5KG1lc3NhZ2UucXVlcnkpO1xuICAgICAgfVxuXG4gICAgICBpZiAobWVzc2FnZS5maWx0ZXJzKSB7XG4gICAgICAgIGRlcHNTdGFydC5kYXRhLnF1ZXJ5LmZpbHRlck1hbmFnZXIuc2V0RmlsdGVycyhtZXNzYWdlLmZpbHRlcnMgYXMgYW55KTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtkZXBzU3RhcnQuZGF0YV1cbiAgKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGNvbnN0IG9uTWVzc2FnZSA9IChldmVudDogTWVzc2FnZUV2ZW50KSA9PiB7XG4gICAgICBpZiAoIWFsbG93ZWRQYXJlbnRPcmlnaW5zUmVmLmN1cnJlbnQuaW5jbHVkZXMoZXZlbnQub3JpZ2luKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICghaXNTd2l0Y2hEYXNoYm9hcmRNZXNzYWdlKGV2ZW50LmRhdGEpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgbGFzdFBhcmVudE9yaWdpblJlZi5jdXJyZW50ID0gZXZlbnQub3JpZ2luO1xuXG4gICAgICBhcHBseVNoYXJlZERhc2hib2FyZFN0YXRlKGV2ZW50LmRhdGEpO1xuICAgICAgc2V0RGFzaGJvYXJkSWQoZXZlbnQuZGF0YS5kYXNoYm9hcmRJZCk7XG4gICAgfTtcblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25NZXNzYWdlKTtcblxuICAgIHBvc3RUb1BhcmVudChcbiAgICAgIHtcbiAgICAgICAgdHlwZTogJ09SR19EQVNIQk9BUkRfRU1CRURfUkVBRFknLFxuICAgICAgICBkYXNoYm9hcmRJZFxuICAgICAgfSxcbiAgICAgIGxhc3RQYXJlbnRPcmlnaW5SZWYuY3VycmVudFxuICAgICk7XG5cbiAgICByZXR1cm4gKCkgPT4gd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbk1lc3NhZ2UpO1xuICB9LCBbYXBwbHlTaGFyZWREYXNoYm9hcmRTdGF0ZSwgZGFzaGJvYXJkSWRdKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmICghZGFzaGJvYXJkSWQgfHwgIXJvb3RSZWYuY3VycmVudCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBjYW5jZWxsZWQgPSBmYWxzZTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJlbmRlckRhc2hib2FyZCgpIHtcbiAgICAgIHNldExvYWRpbmcodHJ1ZSk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGRlc3Ryb3lDdXJyZW50RGFzaGJvYXJkKCk7XG5cbiAgICAgICAgY29uc3QgZmFjdG9yeSA9XG4gICAgICAgICAgZGVwc1N0YXJ0LmVtYmVkZGFibGUuZ2V0RW1iZWRkYWJsZUZhY3Rvcnk/LignZGFzaGJvYXJkJykgfHxcbiAgICAgICAgICBkZXBzU3RhcnQuZW1iZWRkYWJsZS5nZXRFbWJlZGRhYmxlRmFjdG9yeT8uKCdkYXNoYm9hcmRfY29udGFpbmVyJyk7XG5cbiAgICAgICAgaWYgKCFmYWN0b3J5KSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdLaWJhbmEgZGFzaGJvYXJkIGVtYmVkZGFibGUgZmFjdG9yeSB3YXMgbm90IGZvdW5kLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZW1iZWRkYWJsZSA9IGF3YWl0IGZhY3RvcnkuY3JlYXRlKHtcbiAgICAgICAgICBpZDogZGFzaGJvYXJkSWQsXG4gICAgICAgICAgc2F2ZWRPYmplY3RJZDogZGFzaGJvYXJkSWQsXG4gICAgICAgICAgdmlld01vZGU6ICd2aWV3JyxcbiAgICAgICAgICBoaWRlUGFuZWxUaXRsZXM6IGZhbHNlLFxuICAgICAgICAgIHVzZU1hcmdpbnM6IHRydWUsXG4gICAgICAgICAgc3luY0NvbG9yczogdHJ1ZSxcbiAgICAgICAgICBzeW5jQ3Vyc29yOiB0cnVlLFxuICAgICAgICAgIHN5bmNUb29sdGlwczogdHJ1ZSxcbiAgICAgICAgICB0aW1lUmFuZ2U6IGRlcHNTdGFydC5kYXRhLnF1ZXJ5LnRpbWVmaWx0ZXIudGltZWZpbHRlci5nZXRUaW1lKCksXG4gICAgICAgICAgcXVlcnk6IGRlcHNTdGFydC5kYXRhLnF1ZXJ5LnF1ZXJ5U3RyaW5nLmdldFF1ZXJ5KCksXG4gICAgICAgICAgZmlsdGVyczogZGVwc1N0YXJ0LmRhdGEucXVlcnkuZmlsdGVyTWFuYWdlci5nZXRGaWx0ZXJzKClcbiAgICAgICAgfSBhcyBhbnkpO1xuXG4gICAgICAgIGlmIChjYW5jZWxsZWQpIHtcbiAgICAgICAgICBlbWJlZGRhYmxlLmRlc3Ryb3k/LigpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGVtYmVkZGFibGUucmVuZGVyKHJvb3RSZWYuY3VycmVudCEpO1xuICAgICAgICBtb3VudGVkRGFzaGJvYXJkUmVmLmN1cnJlbnQgPSBlbWJlZGRhYmxlO1xuXG4gICAgICAgIHBvc3RUb1BhcmVudChcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnT1JHX0RBU0hCT0FSRF9FTUJFRF9SRU5ERVJFRCcsXG4gICAgICAgICAgICBkYXNoYm9hcmRJZFxuICAgICAgICAgIH0sXG4gICAgICAgICAgbGFzdFBhcmVudE9yaWdpblJlZi5jdXJyZW50XG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zdCBtZXNzYWdlID1cbiAgICAgICAgICBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6ICdVbmtub3duIGRhc2hib2FyZCBlcnJvcic7XG5cbiAgICAgICAgaWYgKHJvb3RSZWYuY3VycmVudCkge1xuICAgICAgICAgIHJvb3RSZWYuY3VycmVudC5pbm5lckhUTUwgPSBcXGBcbiAgICAgICAgICAgIDxkaXYgc3R5bGU9XCJcbiAgICAgICAgICAgICAgcGFkZGluZzogMjRweDtcbiAgICAgICAgICAgICAgZm9udC1mYW1pbHk6IHNhbnMtc2VyaWY7XG4gICAgICAgICAgICAgIGNvbG9yOiAjYmQyNzFlO1xuICAgICAgICAgICAgXCI+XG4gICAgICAgICAgICAgIEZhaWxlZCB0byByZW5kZXIgZGFzaGJvYXJkOiBcXCR7bWVzc2FnZX1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIFxcYDtcbiAgICAgICAgfVxuXG4gICAgICAgIHBvc3RUb1BhcmVudChcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnT1JHX0RBU0hCT0FSRF9FTUJFRF9FUlJPUicsXG4gICAgICAgICAgICBkYXNoYm9hcmRJZCxcbiAgICAgICAgICAgIG1lc3NhZ2VcbiAgICAgICAgICB9LFxuICAgICAgICAgIGxhc3RQYXJlbnRPcmlnaW5SZWYuY3VycmVudFxuICAgICAgICApO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgaWYgKCFjYW5jZWxsZWQpIHtcbiAgICAgICAgICBzZXRMb2FkaW5nKGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJlbmRlckRhc2hib2FyZCgpO1xuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGNhbmNlbGxlZCA9IHRydWU7XG4gICAgfTtcbiAgfSwgW2Rhc2hib2FyZElkLCBkZXBzU3RhcnQsIGRlc3Ryb3lDdXJyZW50RGFzaGJvYXJkXSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgZGVzdHJveUN1cnJlbnREYXNoYm9hcmQoKTtcbiAgICB9O1xuICB9LCBbZGVzdHJveUN1cnJlbnREYXNoYm9hcmRdKTtcblxuICByZXR1cm4gKFxuICAgIDxkaXZcbiAgICAgIHN0eWxlPXt7XG4gICAgICAgIHBvc2l0aW9uOiAnZml4ZWQnLFxuICAgICAgICBpbnNldDogMCxcbiAgICAgICAgd2lkdGg6ICcxMDB2dycsXG4gICAgICAgIGhlaWdodDogJzEwMHZoJyxcbiAgICAgICAgb3ZlcmZsb3c6ICdoaWRkZW4nLFxuICAgICAgICBiYWNrZ3JvdW5kOiAnI2ZmZidcbiAgICAgIH19XG4gICAgPlxuICAgICAge2xvYWRpbmcgJiYgKFxuICAgICAgICA8ZGl2XG4gICAgICAgICAgc3R5bGU9e3tcbiAgICAgICAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuICAgICAgICAgICAgaW5zZXQ6IDAsXG4gICAgICAgICAgICB6SW5kZXg6IDEwLFxuICAgICAgICAgICAgZGlzcGxheTogJ2ZsZXgnLFxuICAgICAgICAgICAgYWxpZ25JdGVtczogJ2NlbnRlcicsXG4gICAgICAgICAgICBqdXN0aWZ5Q29udGVudDogJ2NlbnRlcicsXG4gICAgICAgICAgICBmb250RmFtaWx5OiAnc2Fucy1zZXJpZicsXG4gICAgICAgICAgICBiYWNrZ3JvdW5kOiAnI2ZmZidcbiAgICAgICAgICB9fVxuICAgICAgICA+XG4gICAgICAgICAgTG9hZGluZyBkYXNoYm9hcmTigKZcbiAgICAgICAgPC9kaXY+XG4gICAgICApfVxuXG4gICAgICA8ZGl2XG4gICAgICAgIHJlZj17cm9vdFJlZn1cbiAgICAgICAgc3R5bGU9e3tcbiAgICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgICAgICBpbnNldDogMCxcbiAgICAgICAgICB3aWR0aDogJzEwMCUnLFxuICAgICAgICAgIGhlaWdodDogJzEwMCUnXG4gICAgICAgIH19XG4gICAgICAvPlxuICAgIDwvZGl2PlxuICApO1xufVxuYDtcblxuY29uc3QgU0VSVkVSX0lOREVYID0gYGltcG9ydCB0eXBlIHsgUGx1Z2luSW5pdGlhbGl6ZXJDb250ZXh0IH0gZnJvbSAnQGtibi9jb3JlL3NlcnZlcic7XG5pbXBvcnQgeyBPcmdEYXNoYm9hcmRFbWJlZFNlcnZlclBsdWdpbiB9IGZyb20gJy4vcGx1Z2luJztcblxuZXhwb3J0IGZ1bmN0aW9uIHBsdWdpbihpbml0aWFsaXplckNvbnRleHQ6IFBsdWdpbkluaXRpYWxpemVyQ29udGV4dCkge1xuICByZXR1cm4gbmV3IE9yZ0Rhc2hib2FyZEVtYmVkU2VydmVyUGx1Z2luKGluaXRpYWxpemVyQ29udGV4dCk7XG59XG5gO1xuXG5jb25zdCBTRVJWRVJfUExVR0lOID0gYGltcG9ydCB0eXBlIHtcbiAgQ29yZVNldHVwLFxuICBDb3JlU3RhcnQsXG4gIFBsdWdpbixcbiAgUGx1Z2luSW5pdGlhbGl6ZXJDb250ZXh0XG59IGZyb20gJ0BrYm4vY29yZS9zZXJ2ZXInO1xuXG5leHBvcnQgY2xhc3MgT3JnRGFzaGJvYXJkRW1iZWRTZXJ2ZXJQbHVnaW4gaW1wbGVtZW50cyBQbHVnaW4ge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGluaXRpYWxpemVyQ29udGV4dDogUGx1Z2luSW5pdGlhbGl6ZXJDb250ZXh0KSB7fVxuXG4gIHB1YmxpYyBzZXR1cChjb3JlOiBDb3JlU2V0dXApIHtcbiAgICBjb25zdCByb3V0ZXIgPSBjb3JlLmh0dHAuY3JlYXRlUm91dGVyKCk7XG5cbiAgICByb3V0ZXIuZ2V0KFxuICAgICAge1xuICAgICAgICBwYXRoOiAnL2FwaS8ke0tJQkFOQV9BUFBfSUR9L2hlYWx0aCcsXG4gICAgICAgIHZhbGlkYXRlOiBmYWxzZVxuICAgICAgfSxcbiAgICAgIGFzeW5jIChjb250ZXh0LCByZXF1ZXN0LCByZXNwb25zZSkgPT4ge1xuICAgICAgICByZXR1cm4gcmVzcG9uc2Uub2soe1xuICAgICAgICAgIGJvZHk6IHtcbiAgICAgICAgICAgIG9rOiB0cnVlLFxuICAgICAgICAgICAgcGx1Z2luOiAnJHtLSUJBTkFfQVBQX0lEfSdcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgc3RhcnQoY29yZTogQ29yZVN0YXJ0KSB7fVxuXG4gIHB1YmxpYyBzdG9wKCkge31cbn1cbmA7XG5cbmNvbnN0IFJFQURNRSA9IGAjICR7S0lCQU5BX1BMVUdJTl9JRH1cblxuTXVsdGktdGVuYW50LCBvcmctYWdub3N0aWMgS2liYW5hIGRhc2hib2FyZCBlbWJlZCBwbHVnaW4uXG5cblRoZXJlIGlzIG5ldmVyIHNwYWNlIHN3aXRjaGluZy4gRWFjaCBvcmcgYWxyZWFkeSBsYW5kcyBpbiBpdHMgb3duIEtpYmFuYSBzcGFjZVxudGhyb3VnaCB0aGUgYmFja2VuZCBwcm94eS9zZXNzaW9uIFVSTCwgYW5kIHRoZSBwbHVnaW4gb25seSBzd2l0Y2hlcyBkYXNoYm9hcmRzXG53aXRoaW4gdGhlIGN1cnJlbnQgc3BhY2UuXG5cbiMjIEJ1aWxkXG5cbktpYmFuYSBwbHVnaW5zIG11c3QgbWF0Y2ggdGhlIGV4YWN0IEtpYmFuYSB2ZXJzaW9uIGFuZCBtdXN0IGJlIGJ1aWx0IHdpdGhpbiB0aGVcbktpYmFuYSByZXBvIChzZWUga2JuLXBsdWdpbi1nZW5lcmF0b3IpLiBQbGFjZSB0aGlzIGRpcmVjdG9yeSB1bmRlclxuXFxga2liYW5hLWV4dHJhL1xcYCAob3IgXFxgcGx1Z2lucy9cXGApIGFuZCBydW4gdGhlIEtpYmFuYSBwbHVnaW4gYnVpbGQsIGUuZy46XG5cblxcYFxcYFxcYFxueWFybiBidWlsZFxuXFxgXFxgXFxgXG5cbiMjIEVtYmVkIFVSTFxuXG5cXGBcXGBcXGBcbi9raWJhbmEvYXBwLyR7S0lCQU5BX0FQUF9JRH0/ZGFzaGJvYXJkSWQ9PGlkPiZwYXJlbnRPcmlnaW49PG9yaWdpbj5cblxcYFxcYFxcYFxuXG4jIyBNZXNzYWdlIHByb3RvY29sXG5cbi0gUGFyZW50IC0+IHBsdWdpbjogXFxgT1JHX0RBU0hCT0FSRF9FTUJFRF9TV0lUQ0hfREFTSEJPQVJEXFxgXG4tIFBsdWdpbiAtPiBwYXJlbnQ6IFxcYE9SR19EQVNIQk9BUkRfRU1CRURfUkVBRFlcXGAgLyBcXGBPUkdfREFTSEJPQVJEX0VNQkVEX1JFTkRFUkVEXFxgIC8gXFxgT1JHX0RBU0hCT0FSRF9FTUJFRF9FUlJPUlxcYFxuXG5WZXJzaW9uOiAke0tJQkFOQV9QTFVHSU5fVkVSU0lPTn1cbmA7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgZnVsbCBzZXQgb2YgZ2VuZXJhdGVkIHBsdWdpbiBmaWxlcyBmb3IgYSB0YXJnZXQgS2liYW5hIHZlcnNpb24uXG4gKlxuICogQHBhcmFtIHRhcmdldFZlcnNpb24gLSBLaWJhbmEgdmVyc2lvbiBiYWtlZCBpbnRvIGBraWJhbmEuanNvbmAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBraWJhbmFQbHVnaW5GaWxlcyh0YXJnZXRWZXJzaW9uOiBzdHJpbmcpOiBLaWJhbmFQbHVnaW5GaWxlW10ge1xuICBjb25zdCBtYW5pZmVzdCA9IEpTT04uc3RyaW5naWZ5KFxuICAgIHtcbiAgICAgIGlkOiBLSUJBTkFfUExVR0lOX0lELFxuICAgICAgdmVyc2lvbjogS0lCQU5BX1BMVUdJTl9WRVJTSU9OLFxuICAgICAga2liYW5hVmVyc2lvbjogdGFyZ2V0VmVyc2lvbixcbiAgICAgIHNlcnZlcjogdHJ1ZSxcbiAgICAgIHVpOiB0cnVlLFxuICAgICAgcmVxdWlyZWRQbHVnaW5zOiBbXCJkYXNoYm9hcmRcIiwgXCJlbWJlZGRhYmxlXCIsIFwiZGF0YVwiXSxcbiAgICAgIG9wdGlvbmFsUGx1Z2luczogW10sXG4gICAgfSxcbiAgICBudWxsLFxuICAgIDJcbiAgKTtcblxuICByZXR1cm4gW1xuICAgIHsgcGF0aDogXCJraWJhbmEuanNvblwiLCBjb250ZW50OiBgJHttYW5pZmVzdH1cXG5gIH0sXG4gICAgeyBwYXRoOiBcInRzY29uZmlnLmpzb25cIiwgY29udGVudDogYCR7VFNfQ09ORklHfVxcbmAgfSxcbiAgICB7IHBhdGg6IFwiUkVBRE1FLm1kXCIsIGNvbnRlbnQ6IFJFQURNRSB9LFxuICAgIHsgcGF0aDogXCJwdWJsaWMvdHlwZXMudHNcIiwgY29udGVudDogUFVCTElDX1RZUEVTIH0sXG4gICAgeyBwYXRoOiBcInB1YmxpYy9pbmRleC50c1wiLCBjb250ZW50OiBQVUJMSUNfSU5ERVggfSxcbiAgICB7IHBhdGg6IFwicHVibGljL3BsdWdpbi50c3hcIiwgY29udGVudDogUFVCTElDX1BMVUdJTiB9LFxuICAgIHsgcGF0aDogXCJwdWJsaWMvYXBwbGljYXRpb24udHN4XCIsIGNvbnRlbnQ6IFBVQkxJQ19BUFBMSUNBVElPTiB9LFxuICAgIHsgcGF0aDogXCJzZXJ2ZXIvaW5kZXgudHNcIiwgY29udGVudDogU0VSVkVSX0lOREVYIH0sXG4gICAgeyBwYXRoOiBcInNlcnZlci9wbHVnaW4udHNcIiwgY29udGVudDogU0VSVkVSX1BMVUdJTiB9LFxuICBdO1xufVxuIl19
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module integrations/plugins/kibana/types
|
|
3
|
+
* @summary Kibana embed plugin types.
|
|
4
|
+
* @description Re-exports the shared contract types and exposes Kibana-specific
|
|
5
|
+
* constants/types for the org-agnostic dashboard embed plugin.
|
|
6
|
+
*/
|
|
7
|
+
export * from "./../contract.js";
|
|
8
|
+
export { KIBANA_PLUGIN_ID, KIBANA_APP_ID, KIBANA_PLUGIN_VERSION, buildKibanaManifest, } from "./manifest.js";
|
|
9
|
+
export { kibanaPluginFiles } from "./templates.js";
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvcGx1Z2lucy9raWJhbmEvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFDSCxpQ0FBNEI7QUFDNUIsT0FBTyxFQUNMLGdCQUFnQixFQUNoQixhQUFhLEVBQ2IscUJBQXFCLEVBQ3JCLG1CQUFtQixHQUVwQixzQkFBbUI7QUFDcEIsT0FBTyxFQUFFLGlCQUFpQixFQUF5Qix1QkFBb0IiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBtb2R1bGUgaW50ZWdyYXRpb25zL3BsdWdpbnMva2liYW5hL3R5cGVzXG4gKiBAc3VtbWFyeSBLaWJhbmEgZW1iZWQgcGx1Z2luIHR5cGVzLlxuICogQGRlc2NyaXB0aW9uIFJlLWV4cG9ydHMgdGhlIHNoYXJlZCBjb250cmFjdCB0eXBlcyBhbmQgZXhwb3NlcyBLaWJhbmEtc3BlY2lmaWNcbiAqIGNvbnN0YW50cy90eXBlcyBmb3IgdGhlIG9yZy1hZ25vc3RpYyBkYXNoYm9hcmQgZW1iZWQgcGx1Z2luLlxuICovXG5leHBvcnQgKiBmcm9tIFwiLi4vY29udHJhY3RcIjtcbmV4cG9ydCB7XG4gIEtJQkFOQV9QTFVHSU5fSUQsXG4gIEtJQkFOQV9BUFBfSUQsXG4gIEtJQkFOQV9QTFVHSU5fVkVSU0lPTixcbiAgYnVpbGRLaWJhbmFNYW5pZmVzdCxcbiAgdHlwZSBLaWJhbmFNYW5pZmVzdCxcbn0gZnJvbSBcIi4vbWFuaWZlc3RcIjtcbmV4cG9ydCB7IGtpYmFuYVBsdWdpbkZpbGVzLCB0eXBlIEtpYmFuYVBsdWdpbkZpbGUgfSBmcm9tIFwiLi90ZW1wbGF0ZXNcIjtcbiJdfQ==
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module integrations/plugins/superset/host
|
|
3
|
+
* @summary Angular host-side helpers for the Superset embed plugin.
|
|
4
|
+
* @description DOM-free convenience helpers the Angular host uses to build the
|
|
5
|
+
* embedded URL and send switch-dashboard messages to the embedded Superset
|
|
6
|
+
* plugin via the SDK handle.
|
|
7
|
+
*/
|
|
8
|
+
import { sendSwitchDashboardMessage as sendShared, } from "./../contract.js";
|
|
9
|
+
import { buildSupersetEmbedUrl } from "./installer.js";
|
|
10
|
+
export { buildSupersetEmbedUrl };
|
|
11
|
+
/**
|
|
12
|
+
* Send a switch-dashboard message to the embedded Superset dashboard.
|
|
13
|
+
*
|
|
14
|
+
* The Angular host passes the embedded SDK's `EmbeddedDashboard` handle
|
|
15
|
+
* (wrapped to satisfy `EmbedMessageTarget.switchDashboard`) and the Superset
|
|
16
|
+
* origin as `targetOrigin`.
|
|
17
|
+
*/
|
|
18
|
+
export function sendSupersetSwitchDashboardMessage(target, payload, targetOrigin) {
|
|
19
|
+
sendShared(target, payload, targetOrigin);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9zdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9wbHVnaW5zL3N1cGVyc2V0L2hvc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBQ0gsT0FBTyxFQUNMLDBCQUEwQixJQUFJLFVBQVUsR0FJekMseUJBQW9CO0FBQ3JCLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSx1QkFBb0I7QUFFcEQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLENBQUM7QUFFakM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLGtDQUFrQyxDQUNoRCxNQUEwQixFQUMxQixPQUErQixFQUMvQixZQUFvQjtJQUVwQixVQUFVLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQztBQUM1QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbW9kdWxlIGludGVncmF0aW9ucy9wbHVnaW5zL3N1cGVyc2V0L2hvc3RcbiAqIEBzdW1tYXJ5IEFuZ3VsYXIgaG9zdC1zaWRlIGhlbHBlcnMgZm9yIHRoZSBTdXBlcnNldCBlbWJlZCBwbHVnaW4uXG4gKiBAZGVzY3JpcHRpb24gRE9NLWZyZWUgY29udmVuaWVuY2UgaGVscGVycyB0aGUgQW5ndWxhciBob3N0IHVzZXMgdG8gYnVpbGQgdGhlXG4gKiBlbWJlZGRlZCBVUkwgYW5kIHNlbmQgc3dpdGNoLWRhc2hib2FyZCBtZXNzYWdlcyB0byB0aGUgZW1iZWRkZWQgU3VwZXJzZXRcbiAqIHBsdWdpbiB2aWEgdGhlIFNESyBoYW5kbGUuXG4gKi9cbmltcG9ydCB7XG4gIHNlbmRTd2l0Y2hEYXNoYm9hcmRNZXNzYWdlIGFzIHNlbmRTaGFyZWQsXG4gIHR5cGUgRW1iZWRNZXNzYWdlVGFyZ2V0LFxuICB0eXBlIEVtYmVkVXJsT3B0aW9ucyxcbiAgdHlwZSBTd2l0Y2hEYXNoYm9hcmRQYXlsb2FkLFxufSBmcm9tIFwiLi4vY29udHJhY3RcIjtcbmltcG9ydCB7IGJ1aWxkU3VwZXJzZXRFbWJlZFVybCB9IGZyb20gXCIuL2luc3RhbGxlclwiO1xuXG5leHBvcnQgeyBidWlsZFN1cGVyc2V0RW1iZWRVcmwgfTtcblxuLyoqXG4gKiBTZW5kIGEgc3dpdGNoLWRhc2hib2FyZCBtZXNzYWdlIHRvIHRoZSBlbWJlZGRlZCBTdXBlcnNldCBkYXNoYm9hcmQuXG4gKlxuICogVGhlIEFuZ3VsYXIgaG9zdCBwYXNzZXMgdGhlIGVtYmVkZGVkIFNESydzIGBFbWJlZGRlZERhc2hib2FyZGAgaGFuZGxlXG4gKiAod3JhcHBlZCB0byBzYXRpc2Z5IGBFbWJlZE1lc3NhZ2VUYXJnZXQuc3dpdGNoRGFzaGJvYXJkYCkgYW5kIHRoZSBTdXBlcnNldFxuICogb3JpZ2luIGFzIGB0YXJnZXRPcmlnaW5gLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VuZFN1cGVyc2V0U3dpdGNoRGFzaGJvYXJkTWVzc2FnZShcbiAgdGFyZ2V0OiBFbWJlZE1lc3NhZ2VUYXJnZXQsXG4gIHBheWxvYWQ6IFN3aXRjaERhc2hib2FyZFBheWxvYWQsXG4gIHRhcmdldE9yaWdpbjogc3RyaW5nXG4pOiB2b2lkIHtcbiAgc2VuZFNoYXJlZCh0YXJnZXQsIHBheWxvYWQsIHRhcmdldE9yaWdpbik7XG59XG5cbi8qKiBSZS1leHBvcnQgdGhlIFVSTCBvcHRpb25zIHR5cGUgZm9yIGhvc3QgY29udmVuaWVuY2UuICovXG5leHBvcnQgdHlwZSB7IEVtYmVkVXJsT3B0aW9ucyB9O1xuIl19
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module integrations/plugins/superset
|
|
3
|
+
* @summary Superset dashboard embed plugin surface.
|
|
4
|
+
* @description Org-agnostic multi-tenant Superset dashboard embed plugin
|
|
5
|
+
* (patch-and-build strategy). Same API as the Kibana plugin. Decaf holds
|
|
6
|
+
* patch scripts that modify Superset's internal embedded frontend and SDK
|
|
7
|
+
* source files to add a `switchDashboard` method, keeping the iframe element,
|
|
8
|
+
* document, contentWindow, React runtime, and Switchboard MessageChannel alive.
|
|
9
|
+
*/
|
|
10
|
+
export * from "./../contract.js";
|
|
11
|
+
export * from "./types.js";
|
|
12
|
+
export * from "./manifest.js";
|
|
13
|
+
export * from "./templates.js";
|
|
14
|
+
export { SupersetDashboardEmbedPlugin, supersetDashboardEmbedPlugin, createSupersetDashboardEmbedPlugin, buildSupersetEmbedUrl, SUPERSET_DEFAULT_BASE_PATH, } from "./installer.js";
|
|
15
|
+
export { sendSupersetSwitchDashboardMessage, } from "./host.js";
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvcGx1Z2lucy9zdXBlcnNldC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7R0FRRztBQUNILGlDQUE0QjtBQUM1QiwyQkFBd0I7QUFDeEIsOEJBQTJCO0FBQzNCLCtCQUE0QjtBQUM1QixPQUFPLEVBQ0wsNEJBQTRCLEVBQzVCLDRCQUE0QixFQUM1QixrQ0FBa0MsRUFDbEMscUJBQXFCLEVBQ3JCLDBCQUEwQixHQUUzQix1QkFBb0I7QUFDckIsT0FBTyxFQUNMLGtDQUFrQyxHQUNuQyxrQkFBZSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQG1vZHVsZSBpbnRlZ3JhdGlvbnMvcGx1Z2lucy9zdXBlcnNldFxuICogQHN1bW1hcnkgU3VwZXJzZXQgZGFzaGJvYXJkIGVtYmVkIHBsdWdpbiBzdXJmYWNlLlxuICogQGRlc2NyaXB0aW9uIE9yZy1hZ25vc3RpYyBtdWx0aS10ZW5hbnQgU3VwZXJzZXQgZGFzaGJvYXJkIGVtYmVkIHBsdWdpblxuICogKHBhdGNoLWFuZC1idWlsZCBzdHJhdGVneSkuIFNhbWUgQVBJIGFzIHRoZSBLaWJhbmEgcGx1Z2luLiBEZWNhZiBob2xkc1xuICogcGF0Y2ggc2NyaXB0cyB0aGF0IG1vZGlmeSBTdXBlcnNldCdzIGludGVybmFsIGVtYmVkZGVkIGZyb250ZW5kIGFuZCBTREtcbiAqIHNvdXJjZSBmaWxlcyB0byBhZGQgYSBgc3dpdGNoRGFzaGJvYXJkYCBtZXRob2QsIGtlZXBpbmcgdGhlIGlmcmFtZSBlbGVtZW50LFxuICogZG9jdW1lbnQsIGNvbnRlbnRXaW5kb3csIFJlYWN0IHJ1bnRpbWUsIGFuZCBTd2l0Y2hib2FyZCBNZXNzYWdlQ2hhbm5lbCBhbGl2ZS5cbiAqL1xuZXhwb3J0ICogZnJvbSBcIi4uL2NvbnRyYWN0XCI7XG5leHBvcnQgKiBmcm9tIFwiLi90eXBlc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vbWFuaWZlc3RcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3RlbXBsYXRlc1wiO1xuZXhwb3J0IHtcbiAgU3VwZXJzZXREYXNoYm9hcmRFbWJlZFBsdWdpbixcbiAgc3VwZXJzZXREYXNoYm9hcmRFbWJlZFBsdWdpbixcbiAgY3JlYXRlU3VwZXJzZXREYXNoYm9hcmRFbWJlZFBsdWdpbixcbiAgYnVpbGRTdXBlcnNldEVtYmVkVXJsLFxuICBTVVBFUlNFVF9ERUZBVUxUX0JBU0VfUEFUSCxcbiAgdHlwZSBTdXBlcnNldEluc3RhbGxPcHRpb25zLFxufSBmcm9tIFwiLi9pbnN0YWxsZXJcIjtcbmV4cG9ydCB7XG4gIHNlbmRTdXBlcnNldFN3aXRjaERhc2hib2FyZE1lc3NhZ2UsXG59IGZyb20gXCIuL2hvc3RcIjtcbiJdfQ==
|