@dbx-tools/model 0.3.44 → 0.4.1

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.
@@ -0,0 +1,286 @@
1
+ /**
2
+ * Live Databricks Model Serving catalogue access.
3
+ *
4
+ * Lists the workspace's `/serving-endpoints` once per host and caches the
5
+ * result with a TTL via AppKit's `CacheManager`, with concurrent callers
6
+ * sharing one in-flight promise (the coalescing pattern of Python's
7
+ * `cachetools-async`). Surfaces each endpoint as a stable
8
+ * {@link ServingEndpointSummary} - including the Foundation Model API
9
+ * `quality` / `speed` / `cost` profile when present, the classified
10
+ * {@link ModelClass}, and (for embedding endpoints) the measured vector
11
+ * `dimension` - and snaps loose, human-typed names to real endpoint ids
12
+ * through `fuse.js` extended search so tokens like `"claude sonnet"` resolve to
13
+ * `databricks-claude-sonnet-4-6`.
14
+ *
15
+ * The class stamp and embedding dimension are computed once per cache load:
16
+ * every embedding endpoint is "pinged" in parallel and the resulting vector
17
+ * length recorded, so the cost is paid on a cache miss, not per read. The ping
18
+ * is best-effort - a failure logs at debug and leaves `dimension` unset rather
19
+ * than failing the whole listing.
20
+ *
21
+ * @module
22
+ */
23
+ import { CacheManager } from "@databricks/appkit";
24
+ import { error, log, string } from "@dbx-tools/shared-core";
25
+ import { classify, display, model, } from "@dbx-tools/shared-model";
26
+ import Fuse from "fuse.js";
27
+ import { MODEL_CLASS_ORDER } from "./classes.js";
28
+ const { ModelClass } = model;
29
+ const logger = log.logger("model/serving");
30
+ /** Default TTL for the in-memory endpoint cache. Matches the Databricks SDK's session lifetime budget. */
31
+ export const DEFAULT_MODEL_CACHE_TTL_MS = 5 * 60 * 1000;
32
+ /** Default Fuse.js score threshold below which a fuzzy match is accepted. */
33
+ export const DEFAULT_FUZZY_THRESHOLD = 0.4;
34
+ /** Cache key parts under which endpoint listings are stored. */
35
+ const CACHE_KEY_NAMESPACE = "serving-endpoints";
36
+ /**
37
+ * Stable `userKey` arg for AppKit's `CacheManager.getOrExecute`. Endpoint
38
+ * visibility is effectively workspace-scoped (we cache by host in the key
39
+ * parts), so a single shared key lets every user of the same workspace share
40
+ * one cached fetch and coalesce on the in-flight promise. Permissions can
41
+ * differ in theory, but the Foundation Model API catalogue is the same view for
42
+ * every caller.
43
+ */
44
+ const SHARED_USER_KEY = "model-shared";
45
+ /**
46
+ * List Model Serving endpoints for the workspace owning `client`, routed
47
+ * through AppKit's `CacheManager`. The manager gives us everything
48
+ * `cachetools.TTLCache` provides plus what `cachetools-async` adds on top:
49
+ * per-entry TTL, in-flight request coalescing (concurrent callers share one
50
+ * fetch via the manager's internal `inFlightRequests` map), bounded size,
51
+ * telemetry spans (`cache.getOrExecute`), and optional Lakebase persistence so
52
+ * the catalogue survives restarts when the lakebase plugin is wired up.
53
+ *
54
+ * Returns plain {@link ServingEndpointSummary} objects (a stable subset of the
55
+ * SDK type) so cache hits never expose stale SDK internals. Errors from
56
+ * `CacheManager` or the SDK fetch propagate to the caller - we don't swallow
57
+ * them so users see the real auth / network issue.
58
+ *
59
+ * @param host - Workspace host used as the cache key. Pass the value resolved
60
+ * from `client.config.getHost()` so multi-host apps share one entry per
61
+ * workspace.
62
+ * @param options.ttlMs - Override the default TTL just for this call. Forwarded
63
+ * to `CacheManager` as seconds.
64
+ */
65
+ export async function listServingEndpoints(client, host, options = {}) {
66
+ const ttlSec = Math.max(1, Math.round((options.ttlMs ?? DEFAULT_MODEL_CACHE_TTL_MS) / 1000));
67
+ return CacheManager.getInstanceSync().getOrExecute([CACHE_KEY_NAMESPACE, host], () => fetchEndpoints(client), SHARED_USER_KEY, { ttl: ttlSec });
68
+ }
69
+ /**
70
+ * List the workspace's serving endpoints as minimal
71
+ * {@link ServingEndpointSummary} objects straight from the SDK: no caching, and
72
+ * none of the cache-load enrichment ({@link listServingEndpoints} adds the
73
+ * {@link ModelClass} stamp and the embedding-dimension probe). Use this for a
74
+ * one-shot, dependency-light listing - e.g. a CLI that only needs names/tasks
75
+ * for fuzzy resolution and doesn't want AppKit's `CacheManager` or the
76
+ * per-embedding ping cost. Prefer {@link listServingEndpoints} for the cached,
77
+ * enriched view.
78
+ */
79
+ export async function listServingEndpointsUncached(client) {
80
+ const out = [];
81
+ for await (const ep of client.servingEndpoints.list()) {
82
+ if (!ep.name)
83
+ continue;
84
+ const profile = extractProfile(ep);
85
+ out.push({
86
+ name: ep.name,
87
+ // Prefer a Databricks-provided human name (a display-name tag or an
88
+ // external-model name); else derive a title-cased label from the id.
89
+ displayName: display.toModelDisplayName(ep.name, providedDisplayName(ep)),
90
+ ...(ep.task !== undefined ? { task: ep.task } : {}),
91
+ ...(ep.state?.ready !== undefined ? { state: String(ep.state.ready) } : {}),
92
+ ...(ep.description !== undefined ? { description: ep.description } : {}),
93
+ ...(profile ? { profile } : {}),
94
+ });
95
+ }
96
+ return out;
97
+ }
98
+ /**
99
+ * Pull a Databricks-provided human name off a serving endpoint, if any:
100
+ * a `display_name` / `displayName` / `name` tag first, then an
101
+ * external-model `name` from the served-entity config. Returns `null`
102
+ * when the endpoint carries no explicit name (the common case for
103
+ * Foundation Model API endpoints), so the caller falls back to deriving
104
+ * one from the id.
105
+ */
106
+ function providedDisplayName(ep) {
107
+ const tag = ep.tags?.find((t) => t.key === "display_name" || t.key === "displayName" || t.key === "name");
108
+ const fromTag = string.trimToNull(tag?.value);
109
+ if (fromTag)
110
+ return fromTag;
111
+ for (const entity of ep.config?.served_entities ?? []) {
112
+ const external = string.trimToNull(entity.external_model?.name);
113
+ if (external)
114
+ return external;
115
+ }
116
+ return null;
117
+ }
118
+ async function fetchEndpoints(client) {
119
+ const startedAt = Date.now();
120
+ const out = await listServingEndpointsUncached(client);
121
+ stampModelClasses(out);
122
+ await measureEmbeddingDimensions(client, out);
123
+ logger.debug("listed", { count: out.length, elapsedMs: Date.now() - startedAt });
124
+ return out;
125
+ }
126
+ /**
127
+ * Stamp each summary's {@link ServingEndpointSummary.class} from the relative
128
+ * classification of the whole set. Mutates `summaries` in place. Endpoints the
129
+ * classifier doesn't recognize (custom, unscored, non-LLM) are left without a
130
+ * class.
131
+ */
132
+ function stampModelClasses(summaries) {
133
+ const buckets = classify.classifyEndpoints(summaries);
134
+ const classOf = new Map();
135
+ for (const cls of MODEL_CLASS_ORDER) {
136
+ for (const ep of buckets[cls])
137
+ classOf.set(ep.name, cls);
138
+ }
139
+ for (const summary of summaries) {
140
+ const cls = classOf.get(summary.name);
141
+ if (cls !== undefined)
142
+ summary.class = cls;
143
+ }
144
+ }
145
+ /**
146
+ * Measure the embedding vector dimension of every {@link ModelClass.Embedding}
147
+ * endpoint by pinging it once, all in parallel. Mutates the matching summaries
148
+ * in place with the resulting `dimension`. Runs only on a cache miss (it's
149
+ * called from {@link fetchEndpoints}), so the probe cost is amortized across the
150
+ * cached TTL window. Per-endpoint failures are swallowed (logged at warn) so
151
+ * one unreachable embedding model never fails the listing.
152
+ */
153
+ async function measureEmbeddingDimensions(client, summaries) {
154
+ await Promise.all(summaries
155
+ .filter((s) => s.class === ModelClass.Embedding)
156
+ .map(async (summary) => {
157
+ const dimension = await pingEmbeddingDimension(client, summary.name);
158
+ if (dimension !== undefined)
159
+ summary.dimension = dimension;
160
+ }));
161
+ }
162
+ /**
163
+ * Best-effort embedding dimension probe: query `name` with a tiny `"ping"`
164
+ * input and return the length of the returned vector. Returns `undefined` (and
165
+ * logs at warn) when the endpoint can't be queried or returns no vector - the
166
+ * dimension is informational, never required.
167
+ */
168
+ async function pingEmbeddingDimension(client, name) {
169
+ try {
170
+ const response = await client.servingEndpoints.query({ name, input: "ping" });
171
+ const dimension = response.data?.[0]?.embedding?.length;
172
+ if (typeof dimension === "number" && dimension > 0)
173
+ return dimension;
174
+ logger.warn("embedding ping returned no vector", { name });
175
+ return undefined;
176
+ }
177
+ catch (err) {
178
+ logger.warn("embedding ping failed", { name, error: error.errorMessage(err) });
179
+ return undefined;
180
+ }
181
+ }
182
+ /**
183
+ * Pull the Foundation Model API `quality` / `speed` / `cost` scores off a
184
+ * serving-endpoint listing entry. Databricks returns these under
185
+ * `config.served_entities[].foundation_model.ai_gateway_model_profile`
186
+ * (snake_case at the wire level, preserved verbatim by the SDK), but the field
187
+ * is newer than the typed `FoundationModel` interface, so we read it through a
188
+ * structural cast. Returns `undefined` when no served entity carries a profile
189
+ * (custom models, embeddings, and brand-new endpoints that Databricks has not
190
+ * scored yet).
191
+ */
192
+ function extractProfile(ep) {
193
+ const entities = ep.config?.served_entities;
194
+ if (!entities)
195
+ return undefined;
196
+ for (const entity of entities) {
197
+ const raw = entity.foundation_model?.ai_gateway_model_profile;
198
+ if (!raw)
199
+ continue;
200
+ const profile = {};
201
+ if (Number.isFinite(raw.quality))
202
+ profile.quality = raw.quality;
203
+ if (Number.isFinite(raw.speed))
204
+ profile.speed = raw.speed;
205
+ if (Number.isFinite(raw.cost))
206
+ profile.cost = raw.cost;
207
+ if (Object.keys(profile).length > 0)
208
+ return profile;
209
+ }
210
+ return undefined;
211
+ }
212
+ /**
213
+ * Force-evict cached endpoint listings via AppKit's `CacheManager`. With a
214
+ * `host` deletes that one workspace's entry; without one clears every cache
215
+ * entry on the manager (since `CacheManager` doesn't expose a namespace-scoped
216
+ * clear, this is the brute-force path - fine for tests, avoid in steady-state
217
+ * code).
218
+ */
219
+ export async function clearServingEndpointsCache(host) {
220
+ const cache = CacheManager.getInstanceSync();
221
+ if (host) {
222
+ const key = cache.generateKey([CACHE_KEY_NAMESPACE, host], SHARED_USER_KEY);
223
+ await cache.delete(key);
224
+ }
225
+ else {
226
+ await cache.clear();
227
+ }
228
+ }
229
+ /**
230
+ * Fuzzy-rank endpoints by how closely their `name` matches `input`, best
231
+ * (lowest score) first, keeping only those within `threshold`:
232
+ *
233
+ * 1. An exact name match short-circuits to a single `score: 0` result.
234
+ * 2. Otherwise the input is tokenized (dashes / underscores / spaces become
235
+ * separators) and fed through Fuse.js extended search, which AND-s each
236
+ * token with fuzzy matching enabled - the "tokenized fuzzy match" a caller
237
+ * reaches for when they type `"claude sonnet"` instead of the full endpoint
238
+ * name.
239
+ *
240
+ * Returns `[]` for an empty endpoint list or when `input` tokenizes to nothing,
241
+ * so callers fall back to the raw input and let Databricks surface a clean 404.
242
+ * This multi-result core is shared by {@link resolveModelId} (single best) and
243
+ * the ranked `rankModels` selector.
244
+ */
245
+ export function searchServingEndpoints(input, endpoints, options = {}) {
246
+ if (endpoints.length === 0)
247
+ return [];
248
+ for (const ep of endpoints) {
249
+ if (ep.name === input)
250
+ return [{ endpoint: ep, score: 0 }];
251
+ }
252
+ const threshold = options.threshold ?? DEFAULT_FUZZY_THRESHOLD;
253
+ // Fuse 7.3 has no built-in tokenize hook; in extended search, space-separated
254
+ // tokens are AND-ed with fuzzy matching enabled. We lean on the shared
255
+ // tokenizer so the splitting rules stay consistent with the rest of the toolkit.
256
+ const query = Array.from(string.tokenizeWithOptions({ lowerCase: true, camelCase: false }, input)).join(" ");
257
+ if (!query)
258
+ return [];
259
+ const fuse = new Fuse(endpoints, {
260
+ keys: ["name"],
261
+ threshold,
262
+ ignoreLocation: true,
263
+ includeScore: true,
264
+ useExtendedSearch: true,
265
+ isCaseSensitive: false,
266
+ });
267
+ return fuse
268
+ .search(query)
269
+ .filter((r) => (r.score ?? 0) <= threshold)
270
+ .map((r) => ({ endpoint: r.item, score: r.score ?? 0 }));
271
+ }
272
+ /**
273
+ * Snap a user-supplied model name to the single closest configured serving
274
+ * endpoint via {@link searchServingEndpoints}. Returns the input unchanged with
275
+ * `matched: false` when nothing scores within the threshold (or the catalogue
276
+ * is empty), so a deliberate model id is never silently rewritten to a
277
+ * similar-looking neighbour and the upstream call surfaces the canonical 404.
278
+ */
279
+ export function resolveModelId(input, endpoints, options = {}) {
280
+ const [best] = searchServingEndpoints(input, endpoints, options);
281
+ if (best) {
282
+ return { modelId: best.endpoint.name, matched: true, score: best.score };
283
+ }
284
+ return { modelId: input, matched: false };
285
+ }
286
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFFSCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFbEQsT0FBTyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDNUQsT0FBTyxFQUNMLFFBQVEsRUFDUixPQUFPLEVBQ1AsS0FBSyxHQUdOLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxJQUFJLE1BQU0sU0FBUyxDQUFDO0FBRTNCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUU5QyxNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsS0FBSyxDQUFDO0FBRTdCLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUM7QUFTM0MsMEdBQTBHO0FBQzFHLE1BQU0sQ0FBQyxNQUFNLDBCQUEwQixHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBRXhELDZFQUE2RTtBQUM3RSxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxHQUFHLENBQUM7QUFFM0MsZ0VBQWdFO0FBQ2hFLE1BQU0sbUJBQW1CLEdBQUcsbUJBQW1CLENBQUM7QUFFaEQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sZUFBZSxHQUFHLGNBQWMsQ0FBQztBQVd2Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsb0JBQW9CLENBQ3hDLE1BQTJCLEVBQzNCLElBQVksRUFDWixVQUF1QyxFQUFFO0lBRXpDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJ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QUM7U0FDYixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUMsSUFBSSxTQUFTLENBQUM7U0FDMUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzdELENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUM1QixLQUFhLEVBQ2IsU0FBNEMsRUFDNUMsVUFBK0IsRUFBRTtJQUVqQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsc0JBQXNCLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNqRSxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ1QsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDM0UsQ0FBQztJQUNELE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQztBQUM1QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBMaXZlIERhdGFicmlja3MgTW9kZWwgU2VydmluZyBjYXRhbG9ndWUgYWNjZXNzLlxuICpcbiAqIExpc3RzIHRoZSB3b3Jrc3BhY2UncyBgL3NlcnZpbmctZW5kcG9pbnRzYCBvbmNlIHBlciBob3N0IGFuZCBjYWNoZXMgdGhlXG4gKiByZXN1bHQgd2l0aCBhIFRUTCB2aWEgQXBwS2l0J3MgYENhY2hlTWFuYWdlcmAsIHdpdGggY29uY3VycmVudCBjYWxsZXJzXG4gKiBzaGFyaW5nIG9uZSBpbi1mbGlnaHQgcHJvbWlzZSAodGhlIGNvYWxlc2NpbmcgcGF0dGVybiBvZiBQeXRob24nc1xuICogYGNhY2hldG9vbHMtYXN5bmNgKS4gU3VyZmFjZXMgZWFjaCBlbmRwb2ludCBhcyBhIHN0YWJsZVxuICoge0BsaW5rIFNlcnZpbmdFbmRwb2ludFN1bW1hcnl9IC0gaW5jbHVkaW5nIHRoZSBGb3VuZGF0aW9uIE1vZGVsIEFQSVxuICogYHF1YWxpdHlgIC8gYHNwZWVkYCAvIGBjb3N0YCBwcm9maWxlIHdoZW4gcHJlc2VudCwgdGhlIGNsYXNzaWZpZWRcbiAqIHtAbGluayBNb2RlbENsYXNzfSwgYW5kIChmb3IgZW1iZWRkaW5nIGVuZHBvaW50cykgdGhlIG1lYXN1cmVkIHZlY3RvclxuICogYGRpbWVuc2lvbmAgLSBhbmQgc25hcHMgbG9vc2UsIGh1bWFuLXR5cGVkIG5hbWVzIHRvIHJlYWwgZW5kcG9pbnQgaWRzXG4gKiB0aHJvdWdoIGBmdXNlLmpzYCBleHRlbmRlZCBzZWFyY2ggc28gdG9rZW5zIGxpa2UgYFwiY2xhdWRlIHNvbm5ldFwiYCByZXNvbHZlIHRvXG4gKiBgZGF0YWJyaWNrcy1jbGF1ZGUtc29ubmV0LTQtNmAuXG4gKlxuICogVGhlIGNsYXNzIHN0YW1wIGFuZCBlbWJlZGRpbmcgZGltZW5zaW9uIGFyZSBjb21wdXRlZCBvbmNlIHBlciBjYWNoZSBsb2FkOlxuICogZXZlcnkgZW1iZWRkaW5nIGVuZHBvaW50IGlzIFwicGluZ2VkXCIgaW4gcGFyYWxsZWwgYW5kIHRoZSByZXN1bHRpbmcgdmVjdG9yXG4gKiBsZW5ndGggcmVjb3JkZWQsIHNvIHRoZSBjb3N0IGlzIHBhaWQgb24gYSBjYWNoZSBtaXNzLCBub3QgcGVyIHJlYWQuIFRoZSBwaW5nXG4gKiBpcyBiZXN0LWVmZm9ydCAtIGEgZmFpbHVyZSBsb2dzIGF0IGRlYnVnIGFuZCBsZWF2ZXMgYGRpbWVuc2lvbmAgdW5zZXQgcmF0aGVyXG4gKiB0aGFuIGZhaWxpbmcgdGhlIHdob2xlIGxpc3RpbmcuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IENhY2hlTWFuYWdlciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGFwcGtpdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuaW1wb3J0IHsgZXJyb3IsIGxvZywgc3RyaW5nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7XG4gIGNsYXNzaWZ5LFxuICBkaXNwbGF5LFxuICBtb2RlbCxcbiAgdHlwZSBNb2RlbFByb2ZpbGUsXG4gIHR5cGUgU2VydmluZ0VuZHBvaW50U3VtbWFyeSxcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1vZGVsXCI7XG5pbXBvcnQgRnVzZSBmcm9tIFwiZnVzZS5qc1wiO1xuXG5pbXBvcnQgeyBNT0RFTF9DTEFTU19PUkRFUiB9IGZyb20gXCIuL2NsYXNzZXNcIjtcblxuY29uc3QgeyBNb2RlbENsYXNzIH0gPSBtb2RlbDtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcIm1vZGVsL3NlcnZpbmdcIik7XG5cbi8qKlxuICogU3RydWN0dXJhbCB0eXBlIGZvciB0aGUgRGF0YWJyaWNrcyB3b3Jrc3BhY2UgY2xpZW50LCByZS1leHBvcnRlZCBzbyB0aGUgcmVzdFxuICogb2YgdGhpcyBwYWNrYWdlIGNhbiBrZWVwIGltcG9ydGluZyBpdCBmcm9tIGhlcmUuIFNlZVxuICogYGFwcGtpdC5Xb3Jrc3BhY2VDbGllbnRMaWtlYCAobm9kZS1hcHBraXQpIGZvciB0aGUgY2Fub25pY2FsIGRlZmluaXRpb24uXG4gKi9cbmV4cG9ydCB0eXBlIFdvcmtzcGFjZUNsaWVudExpa2UgPSBhcHBraXQuV29ya3NwYWNlQ2xpZW50TGlrZTtcblxuLyoqIERlZmF1bHQgVFRMIGZvciB0aGUgaW4tbWVtb3J5IGVuZHBvaW50IGNhY2hlLiBNYXRjaGVzIHRoZSBEYXRhYnJpY2tzIFNESydzIHNlc3Npb24gbGlmZXRpbWUgYnVkZ2V0LiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfTU9ERUxfQ0FDSEVfVFRMX01TID0gNSAqIDYwICogMTAwMDtcblxuLyoqIERlZmF1bHQgRnVzZS5qcyBzY29yZSB0aHJlc2hvbGQgYmVsb3cgd2hpY2ggYSBmdXp6eSBtYXRjaCBpcyBhY2NlcHRlZC4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0ZVWlpZX1RIUkVTSE9MRCA9IDAuNDtcblxuLyoqIENhY2hlIGtleSBwYXJ0cyB1bmRlciB3aGljaCBlbmRwb2ludCBsaXN0aW5ncyBhcmUgc3RvcmVkLiAqL1xuY29uc3QgQ0FDSEVfS0VZX05BTUVTUEFDRSA9IFwic2VydmluZy1lbmRwb2ludHNcIjtcblxuLyoqXG4gKiBTdGFibGUgYHVzZXJLZXlgIGFyZyBmb3IgQXBwS2l0J3MgYENhY2hlTWFuYWdlci5nZXRPckV4ZWN1dGVgLiBFbmRwb2ludFxuICogdmlzaWJpbGl0eSBpcyBlZmZlY3RpdmVseSB3b3Jrc3BhY2Utc2NvcGVkICh3ZSBjYWNoZSBieSBob3N0IGluIHRoZSBrZXlcbiAqIHBhcnRzKSwgc28gYSBzaW5nbGUgc2hhcmVkIGtleSBsZXRzIGV2ZXJ5IHVzZXIgb2YgdGhlIHNhbWUgd29ya3NwYWNlIHNoYXJlXG4gKiBvbmUgY2FjaGVkIGZldGNoIGFuZCBjb2FsZXNjZSBvbiB0aGUgaW4tZmxpZ2h0IHByb21pc2UuIFBlcm1pc3Npb25zIGNhblxuICogZGlmZmVyIGluIHRoZW9yeSwgYnV0IHRoZSBGb3VuZGF0aW9uIE1vZGVsIEFQSSBjYXRhbG9ndWUgaXMgdGhlIHNhbWUgdmlldyBmb3JcbiAqIGV2ZXJ5IGNhbGxlci5cbiAqL1xuY29uc3QgU0hBUkVEX1VTRVJfS0VZID0gXCJtb2RlbC1zaGFyZWRcIjtcblxuLyoqIE9wdGlvbnMgZm9yIHtAbGluayBsaXN0U2VydmluZ0VuZHBvaW50c30uICovXG5leHBvcnQgaW50ZXJmYWNlIExpc3RTZXJ2aW5nRW5kcG9pbnRzT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBPdmVycmlkZSB0aGUgZGVmYXVsdCBjYWNoZSBUVEwgZm9yIHRoaXMgY2FsbCwgaW4gbWlsbGlzZWNvbmRzLiBGb3J3YXJkZWQgdG9cbiAgICogYENhY2hlTWFuYWdlcmAgYXMgc2Vjb25kcy5cbiAgICovXG4gIHR0bE1zPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIExpc3QgTW9kZWwgU2VydmluZyBlbmRwb2ludHMgZm9yIHRoZSB3b3Jrc3BhY2Ugb3duaW5nIGBjbGllbnRgLCByb3V0ZWRcbiAqIHRocm91Z2ggQXBwS2l0J3MgYENhY2hlTWFuYWdlcmAuIFRoZSBtYW5hZ2VyIGdpdmVzIHVzIGV2ZXJ5dGhpbmdcbiAqIGBjYWNoZXRvb2xzLlRUTENhY2hlYCBwcm92aWRlcyBwbHVzIHdoYXQgYGNhY2hldG9vbHMtYXN5bmNgIGFkZHMgb24gdG9wOlxuICogcGVyLWVudHJ5IFRUTCwgaW4tZmxpZ2h0IHJlcXVlc3QgY29hbGVzY2luZyAoY29uY3VycmVudCBjYWxsZXJzIHNoYXJlIG9uZVxuICogZmV0Y2ggdmlhIHRoZSBtYW5hZ2VyJ3MgaW50ZXJuYWwgYGluRmxpZ2h0UmVxdWVzdHNgIG1hcCksIGJvdW5kZWQgc2l6ZSxcbiAqIHRlbGVtZXRyeSBzcGFucyAoYGNhY2hlLmdldE9yRXhlY3V0ZWApLCBhbmQgb3B0aW9uYWwgTGFrZWJhc2UgcGVyc2lzdGVuY2Ugc29cbiAqIHRoZSBjYXRhbG9ndWUgc3Vydml2ZXMgcmVzdGFydHMgd2hlbiB0aGUgbGFrZWJhc2UgcGx1Z2luIGlzIHdpcmVkIHVwLlxuICpcbiAqIFJldHVybnMgcGxhaW4ge0BsaW5rIFNlcnZpbmdFbmRwb2ludFN1bW1hcnl9IG9iamVjdHMgKGEgc3RhYmxlIHN1YnNldCBvZiB0aGVcbiAqIFNESyB0eXBlKSBzbyBjYWNoZSBoaXRzIG5ldmVyIGV4cG9zZSBzdGFsZSBTREsgaW50ZXJuYWxzLiBFcnJvcnMgZnJvbVxuICogYENhY2hlTWFuYWdlcmAgb3IgdGhlIFNESyBmZXRjaCBwcm9wYWdhdGUgdG8gdGhlIGNhbGxlciAtIHdlIGRvbid0IHN3YWxsb3dcbiAqIHRoZW0gc28gdXNlcnMgc2VlIHRoZSByZWFsIGF1dGggLyBuZXR3b3JrIGlzc3VlLlxuICpcbiAqIEBwYXJhbSBob3N0IC0gV29ya3NwYWNlIGhvc3QgdXNlZCBhcyB0aGUgY2FjaGUga2V5LiBQYXNzIHRoZSB2YWx1ZSByZXNvbHZlZFxuICogICBmcm9tIGBjbGllbnQuY29uZmlnLmdldEhvc3QoKWAgc28gbXVsdGktaG9zdCBhcHBzIHNoYXJlIG9uZSBlbnRyeSBwZXJcbiAqICAgd29ya3NwYWNlLlxuICogQHBhcmFtIG9wdGlvbnMudHRsTXMgLSBPdmVycmlkZSB0aGUgZGVmYXVsdCBUVEwganVzdCBmb3IgdGhpcyBjYWxsLiBGb3J3YXJkZWRcbiAqICAgdG8gYENhY2hlTWFuYWdlcmAgYXMgc2Vjb25kcy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxpc3RTZXJ2aW5nRW5kcG9pbnRzKFxuICBjbGllbnQ6IFdvcmtzcGFjZUNsaWVudExpa2UsXG4gIGhvc3Q6IHN0cmluZyxcbiAgb3B0aW9uczogTGlzdFNlcnZpbmdFbmRwb2ludHNPcHRpb25zID0ge30sXG4pOiBQcm9taXNlPFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXT4ge1xuICBjb25zdCB0dGxTZWMgPSBNYXRoLm1heCgxLCBNYXRoLnJvdW5kKChvcHRpb25zLnR0bE1zID8/IERFRkFVTFRfTU9ERUxfQ0FDSEVfVFRMX01TKSAvIDEwMDApKTtcbiAgcmV0dXJuIENhY2hlTWFuYWdlci5nZXRJbnN0YW5jZVN5bmMoKS5nZXRPckV4ZWN1dGUoXG4gICAgW0NBQ0hFX0tFWV9OQU1FU1BBQ0UsIGhvc3RdLFxuICAgICgpID0+IGZldGNoRW5kcG9pbnRzKGNsaWVudCksXG4gICAgU0hBUkVEX1VTRVJfS0VZLFxuICAgIHsgdHRsOiB0dGxTZWMgfSxcbiAgKTtcbn1cblxuLyoqXG4gKiBMaXN0IHRoZSB3b3Jrc3BhY2UncyBzZXJ2aW5nIGVuZHBvaW50cyBhcyBtaW5pbWFsXG4gKiB7QGxpbmsgU2VydmluZ0VuZHBvaW50U3VtbWFyeX0gb2JqZWN0cyBzdHJhaWdodCBmcm9tIHRoZSBTREs6IG5vIGNhY2hpbmcsIGFuZFxuICogbm9uZSBvZiB0aGUgY2FjaGUtbG9hZCBlbnJpY2htZW50ICh7QGxpbmsgbGlzdFNlcnZpbmdFbmRwb2ludHN9IGFkZHMgdGhlXG4gKiB7QGxpbmsgTW9kZWxDbGFzc30gc3RhbXAgYW5kIHRoZSBlbWJlZGRpbmctZGltZW5zaW9uIHByb2JlKS4gVXNlIHRoaXMgZm9yIGFcbiAqIG9uZS1zaG90LCBkZXBlbmRlbmN5LWxpZ2h0IGxpc3RpbmcgLSBlLmcuIGEgQ0xJIHRoYXQgb25seSBuZWVkcyBuYW1lcy90YXNrc1xuICogZm9yIGZ1enp5IHJlc29sdXRpb24gYW5kIGRvZXNuJ3Qgd2FudCBBcHBLaXQncyBgQ2FjaGVNYW5hZ2VyYCBvciB0aGVcbiAqIHBlci1lbWJlZGRpbmcgcGluZyBjb3N0LiBQcmVmZXIge0BsaW5rIGxpc3RTZXJ2aW5nRW5kcG9pbnRzfSBmb3IgdGhlIGNhY2hlZCxcbiAqIGVucmljaGVkIHZpZXcuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaXN0U2VydmluZ0VuZHBvaW50c1VuY2FjaGVkKFxuICBjbGllbnQ6IFdvcmtzcGFjZUNsaWVudExpa2UsXG4pOiBQcm9taXNlPFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXT4ge1xuICBjb25zdCBvdXQ6IFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXSA9IFtdO1xuICBmb3IgYXdhaXQgKGNvbnN0IGVwIG9mIGNsaWVudC5zZXJ2aW5nRW5kcG9pbnRzLmxpc3QoKSkge1xuICAgIGlmICghZXAubmFtZSkgY29udGludWU7XG4gICAgY29uc3QgcHJvZmlsZSA9IGV4dHJhY3RQcm9maWxlKGVwKTtcbiAgICBvdXQucHVzaCh7XG4gICAgICBuYW1lOiBlcC5uYW1lLFxuICAgICAgLy8gUHJlZmVyIGEgRGF0YWJyaWNrcy1wcm92aWRlZCBodW1hbiBuYW1lIChhIGRpc3BsYXktbmFtZSB0YWcgb3IgYW5cbiAgICAgIC8vIGV4dGVybmFsLW1vZGVsIG5hbWUpOyBlbHNlIGRlcml2ZSBhIHRpdGxlLWNhc2VkIGxhYmVsIGZyb20gdGhlIGlkLlxuICAgICAgZGlzcGxheU5hbWU6IGRpc3BsYXkudG9Nb2RlbERpc3BsYXlOYW1lKGVwLm5hbWUsIHByb3ZpZGVkRGlzcGxheU5hbWUoZXApKSxcbiAgICAgIC4uLihlcC50YXNrICE9PSB1bmRlZmluZWQgPyB7IHRhc2s6IGVwLnRhc2sgfSA6IHt9KSxcbiAgICAgIC4uLihlcC5zdGF0ZT8ucmVhZHkgIT09IHVuZGVmaW5lZCA/IHsgc3RhdGU6IFN0cmluZyhlcC5zdGF0ZS5yZWFkeSkgfSA6IHt9KSxcbiAgICAgIC4uLihlcC5kZXNjcmlwdGlvbiAhPT0gdW5kZWZpbmVkID8geyBkZXNjcmlwdGlvbjogZXAuZGVzY3JpcHRpb24gfSA6IHt9KSxcbiAgICAgIC4uLihwcm9maWxlID8geyBwcm9maWxlIH0gOiB7fSksXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqXG4gKiBQdWxsIGEgRGF0YWJyaWNrcy1wcm92aWRlZCBodW1hbiBuYW1lIG9mZiBhIHNlcnZpbmcgZW5kcG9pbnQsIGlmIGFueTpcbiAqIGEgYGRpc3BsYXlfbmFtZWAgLyBgZGlzcGxheU5hbWVgIC8gYG5hbWVgIHRhZyBmaXJzdCwgdGhlbiBhblxuICogZXh0ZXJuYWwtbW9kZWwgYG5hbWVgIGZyb20gdGhlIHNlcnZlZC1lbnRpdHkgY29uZmlnLiBSZXR1cm5zIGBudWxsYFxuICogd2hlbiB0aGUgZW5kcG9pbnQgY2FycmllcyBubyBleHBsaWNpdCBuYW1lICh0aGUgY29tbW9uIGNhc2UgZm9yXG4gKiBGb3VuZGF0aW9uIE1vZGVsIEFQSSBlbmRwb2ludHMpLCBzbyB0aGUgY2FsbGVyIGZhbGxzIGJhY2sgdG8gZGVyaXZpbmdcbiAqIG9uZSBmcm9tIHRoZSBpZC5cbiAqL1xuZnVuY3Rpb24gcHJvdmlkZWREaXNwbGF5TmFtZShlcDoge1xuICB0YWdzPzogQXJyYXk8eyBrZXk6IHN0cmluZzsgdmFsdWU/OiBzdHJpbmcgfT47XG4gIGNvbmZpZz86IHsgc2VydmVkX2VudGl0aWVzPzogQXJyYXk8eyBleHRlcm5hbF9tb2RlbD86IHsgbmFtZT86IHN0cmluZyB9IH0+IH07XG59KTogc3RyaW5nIHwgbnVsbCB7XG4gIGNvbnN0IHRhZyA9IGVwLnRhZ3M/LmZpbmQoXG4gICAgKHQpID0+IHQua2V5ID09PSBcImRpc3BsYXlfbmFtZVwiIHx8IHQua2V5ID09PSBcImRpc3BsYXlOYW1lXCIgfHwgdC5rZXkgPT09IFwibmFtZVwiLFxuICApO1xuICBjb25zdCBmcm9tVGFnID0gc3RyaW5nLnRyaW1Ub051bGwodGFnPy52YWx1ZSk7XG4gIGlmIChmcm9tVGFnKSByZXR1cm4gZnJvbVRhZztcbiAgZm9yIChjb25zdCBlbnRpdHkgb2YgZXAuY29uZmlnPy5zZXJ2ZWRfZW50aXRpZXMgPz8gW10pIHtcbiAgICBjb25zdCBleHRlcm5hbCA9IHN0cmluZy50cmltVG9OdWxsKGVudGl0eS5leHRlcm5hbF9tb2RlbD8ubmFtZSk7XG4gICAgaWYgKGV4dGVybmFsKSByZXR1cm4gZXh0ZXJuYWw7XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZldGNoRW5kcG9pbnRzKGNsaWVudDogV29ya3NwYWNlQ2xpZW50TGlrZSk6IFByb21pc2U8U2VydmluZ0VuZHBvaW50U3VtbWFyeVtdPiB7XG4gIGNvbnN0IHN0YXJ0ZWRBdCA9IERhdGUubm93KCk7XG4gIGNvbnN0IG91dCA9IGF3YWl0IGxpc3RTZXJ2aW5nRW5kcG9pbnRzVW5jYWNoZWQoY2xpZW50KTtcbiAgc3RhbXBNb2RlbENsYXNzZXMob3V0KTtcbiAgYXdhaXQgbWVhc3VyZUVtYmVkZGluZ0RpbWVuc2lvbnMoY2xpZW50LCBvdXQpO1xuICBsb2dnZXIuZGVidWcoXCJsaXN0ZWRcIiwgeyBjb3VudDogb3V0Lmxlbmd0aCwgZWxhcHNlZE1zOiBEYXRlLm5vdygpIC0gc3RhcnRlZEF0IH0pO1xuICByZXR1cm4gb3V0O1xufVxuXG4vKipcbiAqIFN0YW1wIGVhY2ggc3VtbWFyeSdzIHtAbGluayBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5LmNsYXNzfSBmcm9tIHRoZSByZWxhdGl2ZVxuICogY2xhc3NpZmljYXRpb24gb2YgdGhlIHdob2xlIHNldC4gTXV0YXRlcyBgc3VtbWFyaWVzYCBpbiBwbGFjZS4gRW5kcG9pbnRzIHRoZVxuICogY2xhc3NpZmllciBkb2Vzbid0IHJlY29nbml6ZSAoY3VzdG9tLCB1bnNjb3JlZCwgbm9uLUxMTSkgYXJlIGxlZnQgd2l0aG91dCBhXG4gKiBjbGFzcy5cbiAqL1xuZnVuY3Rpb24gc3RhbXBNb2RlbENsYXNzZXMoc3VtbWFyaWVzOiBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5W10pOiB2b2lkIHtcbiAgY29uc3QgYnVja2V0cyA9IGNsYXNzaWZ5LmNsYXNzaWZ5RW5kcG9pbnRzKHN1bW1hcmllcyk7XG4gIGNvbnN0IGNsYXNzT2YgPSBuZXcgTWFwPHN0cmluZywgbW9kZWwuTW9kZWxDbGFzcz4oKTtcbiAgZm9yIChjb25zdCBjbHMgb2YgTU9ERUxfQ0xBU1NfT1JERVIpIHtcbiAgICBmb3IgKGNvbnN0IGVwIG9mIGJ1Y2tldHNbY2xzXSkgY2xhc3NPZi5zZXQoZXAubmFtZSwgY2xzKTtcbiAgfVxuICBmb3IgKGNvbnN0IHN1bW1hcnkgb2Ygc3VtbWFyaWVzKSB7XG4gICAgY29uc3QgY2xzID0gY2xhc3NPZi5nZXQoc3VtbWFyeS5uYW1lKTtcbiAgICBpZiAoY2xzICE9PSB1bmRlZmluZWQpIHN1bW1hcnkuY2xhc3MgPSBjbHM7XG4gIH1cbn1cblxuLyoqXG4gKiBNZWFzdXJlIHRoZSBlbWJlZGRpbmcgdmVjdG9yIGRpbWVuc2lvbiBvZiBldmVyeSB7QGxpbmsgTW9kZWxDbGFzcy5FbWJlZGRpbmd9XG4gKiBlbmRwb2ludCBieSBwaW5naW5nIGl0IG9uY2UsIGFsbCBpbiBwYXJhbGxlbC4gTXV0YXRlcyB0aGUgbWF0Y2hpbmcgc3VtbWFyaWVzXG4gKiBpbiBwbGFjZSB3aXRoIHRoZSByZXN1bHRpbmcgYGRpbWVuc2lvbmAuIFJ1bnMgb25seSBvbiBhIGNhY2hlIG1pc3MgKGl0J3NcbiAqIGNhbGxlZCBmcm9tIHtAbGluayBmZXRjaEVuZHBvaW50c30pLCBzbyB0aGUgcHJvYmUgY29zdCBpcyBhbW9ydGl6ZWQgYWNyb3NzIHRoZVxuICogY2FjaGVkIFRUTCB3aW5kb3cuIFBlci1lbmRwb2ludCBmYWlsdXJlcyBhcmUgc3dhbGxvd2VkIChsb2dnZWQgYXQgd2Fybikgc29cbiAqIG9uZSB1bnJlYWNoYWJsZSBlbWJlZGRpbmcgbW9kZWwgbmV2ZXIgZmFpbHMgdGhlIGxpc3RpbmcuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIG1lYXN1cmVFbWJlZGRpbmdEaW1lbnNpb25zKFxuICBjbGllbnQ6IFdvcmtzcGFjZUNsaWVudExpa2UsXG4gIHN1bW1hcmllczogU2VydmluZ0VuZHBvaW50U3VtbWFyeVtdLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IFByb21pc2UuYWxsKFxuICAgIHN1bW1hcmllc1xuICAgICAgLmZpbHRlcigocykgPT4gcy5jbGFzcyA9PT0gTW9kZWxDbGFzcy5FbWJlZGRpbmcpXG4gICAgICAubWFwKGFzeW5jIChzdW1tYXJ5KSA9PiB7XG4gICAgICAgIGNvbnN0IGRpbWVuc2lvbiA9IGF3YWl0IHBpbmdFbWJlZGRpbmdEaW1lbnNpb24oY2xpZW50LCBzdW1tYXJ5Lm5hbWUpO1xuICAgICAgICBpZiAoZGltZW5zaW9uICE9PSB1bmRlZmluZWQpIHN1bW1hcnkuZGltZW5zaW9uID0gZGltZW5zaW9uO1xuICAgICAgfSksXG4gICk7XG59XG5cbi8qKlxuICogQmVzdC1lZmZvcnQgZW1iZWRkaW5nIGRpbWVuc2lvbiBwcm9iZTogcXVlcnkgYG5hbWVgIHdpdGggYSB0aW55IGBcInBpbmdcImBcbiAqIGlucHV0IGFuZCByZXR1cm4gdGhlIGxlbmd0aCBvZiB0aGUgcmV0dXJuZWQgdmVjdG9yLiBSZXR1cm5zIGB1bmRlZmluZWRgIChhbmRcbiAqIGxvZ3MgYXQgd2Fybikgd2hlbiB0aGUgZW5kcG9pbnQgY2FuJ3QgYmUgcXVlcmllZCBvciByZXR1cm5zIG5vIHZlY3RvciAtIHRoZVxuICogZGltZW5zaW9uIGlzIGluZm9ybWF0aW9uYWwsIG5ldmVyIHJlcXVpcmVkLlxuICovXG5hc3luYyBmdW5jdGlvbiBwaW5nRW1iZWRkaW5nRGltZW5zaW9uKFxuICBjbGllbnQ6IFdvcmtzcGFjZUNsaWVudExpa2UsXG4gIG5hbWU6IHN0cmluZyxcbik6IFByb21pc2U8bnVtYmVyIHwgdW5kZWZpbmVkPiB7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQuc2VydmluZ0VuZHBvaW50cy5xdWVyeSh7IG5hbWUsIGlucHV0OiBcInBpbmdcIiB9KTtcbiAgICBjb25zdCBkaW1lbnNpb24gPSByZXNwb25zZS5kYXRhPy5bMF0/LmVtYmVkZGluZz8ubGVuZ3RoO1xuICAgIGlmICh0eXBlb2YgZGltZW5zaW9uID09PSBcIm51bWJlclwiICYmIGRpbWVuc2lvbiA+IDApIHJldHVybiBkaW1lbnNpb247XG4gICAgbG9nZ2VyLndhcm4oXCJlbWJlZGRpbmcgcGluZyByZXR1cm5lZCBubyB2ZWN0b3JcIiwgeyBuYW1lIH0pO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGxvZ2dlci53YXJuKFwiZW1iZWRkaW5nIHBpbmcgZmFpbGVkXCIsIHsgbmFtZSwgZXJyb3I6IGVycm9yLmVycm9yTWVzc2FnZShlcnIpIH0pO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqXG4gKiBQdWxsIHRoZSBGb3VuZGF0aW9uIE1vZGVsIEFQSSBgcXVhbGl0eWAgLyBgc3BlZWRgIC8gYGNvc3RgIHNjb3JlcyBvZmYgYVxuICogc2VydmluZy1lbmRwb2ludCBsaXN0aW5nIGVudHJ5LiBEYXRhYnJpY2tzIHJldHVybnMgdGhlc2UgdW5kZXJcbiAqIGBjb25maWcuc2VydmVkX2VudGl0aWVzW10uZm91bmRhdGlvbl9tb2RlbC5haV9nYXRld2F5X21vZGVsX3Byb2ZpbGVgXG4gKiAoc25ha2VfY2FzZSBhdCB0aGUgd2lyZSBsZXZlbCwgcHJlc2VydmVkIHZlcmJhdGltIGJ5IHRoZSBTREspLCBidXQgdGhlIGZpZWxkXG4gKiBpcyBuZXdlciB0aGFuIHRoZSB0eXBlZCBgRm91bmRhdGlvbk1vZGVsYCBpbnRlcmZhY2UsIHNvIHdlIHJlYWQgaXQgdGhyb3VnaCBhXG4gKiBzdHJ1Y3R1cmFsIGNhc3QuIFJldHVybnMgYHVuZGVmaW5lZGAgd2hlbiBubyBzZXJ2ZWQgZW50aXR5IGNhcnJpZXMgYSBwcm9maWxlXG4gKiAoY3VzdG9tIG1vZGVscywgZW1iZWRkaW5ncywgYW5kIGJyYW5kLW5ldyBlbmRwb2ludHMgdGhhdCBEYXRhYnJpY2tzIGhhcyBub3RcbiAqIHNjb3JlZCB5ZXQpLlxuICovXG5mdW5jdGlvbiBleHRyYWN0UHJvZmlsZShlcDogdW5rbm93bik6IE1vZGVsUHJvZmlsZSB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGVudGl0aWVzID0gKFxuICAgIGVwIGFzIHtcbiAgICAgIGNvbmZpZz86IHtcbiAgICAgICAgc2VydmVkX2VudGl0aWVzPzogQXJyYXk8e1xuICAgICAgICAgIGZvdW5kYXRpb25fbW9kZWw/OiB7XG4gICAgICAgICAgICBhaV9nYXRld2F5X21vZGVsX3Byb2ZpbGU/OiB7XG4gICAgICAgICAgICAgIHF1YWxpdHk/OiBudW1iZXI7XG4gICAgICAgICAgICAgIHNwZWVkPzogbnVtYmVyO1xuICAgICAgICAgICAgICBjb3N0PzogbnVtYmVyO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9O1xuICAgICAgICB9PjtcbiAgICAgIH07XG4gICAgfVxuICApLmNvbmZpZz8uc2VydmVkX2VudGl0aWVzO1xuICBpZiAoIWVudGl0aWVzKSByZXR1cm4gdW5kZWZpbmVkO1xuICBmb3IgKGNvbnN0IGVudGl0eSBvZiBlbnRpdGllcykge1xuICAgIGNvbnN0IHJhdyA9IGVudGl0eS5mb3VuZGF0aW9uX21vZGVsPy5haV9nYXRld2F5X21vZGVsX3Byb2ZpbGU7XG4gICAgaWYgKCFyYXcpIGNvbnRpbnVlO1xuICAgIGNvbnN0IHByb2ZpbGU6IE1vZGVsUHJvZmlsZSA9IHt9O1xuICAgIGlmIChOdW1iZXIuaXNGaW5pdGUocmF3LnF1YWxpdHkpKSBwcm9maWxlLnF1YWxpdHkgPSByYXcucXVhbGl0eTtcbiAgICBpZiAoTnVtYmVyLmlzRmluaXRlKHJhdy5zcGVlZCkpIHByb2ZpbGUuc3BlZWQgPSByYXcuc3BlZWQ7XG4gICAgaWYgKE51bWJlci5pc0Zpbml0ZShyYXcuY29zdCkpIHByb2ZpbGUuY29zdCA9IHJhdy5jb3N0O1xuICAgIGlmIChPYmplY3Qua2V5cyhwcm9maWxlKS5sZW5ndGggPiAwKSByZXR1cm4gcHJvZmlsZTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIEZvcmNlLWV2aWN0IGNhY2hlZCBlbmRwb2ludCBsaXN0aW5ncyB2aWEgQXBwS2l0J3MgYENhY2hlTWFuYWdlcmAuIFdpdGggYVxuICogYGhvc3RgIGRlbGV0ZXMgdGhhdCBvbmUgd29ya3NwYWNlJ3MgZW50cnk7IHdpdGhvdXQgb25lIGNsZWFycyBldmVyeSBjYWNoZVxuICogZW50cnkgb24gdGhlIG1hbmFnZXIgKHNpbmNlIGBDYWNoZU1hbmFnZXJgIGRvZXNuJ3QgZXhwb3NlIGEgbmFtZXNwYWNlLXNjb3BlZFxuICogY2xlYXIsIHRoaXMgaXMgdGhlIGJydXRlLWZvcmNlIHBhdGggLSBmaW5lIGZvciB0ZXN0cywgYXZvaWQgaW4gc3RlYWR5LXN0YXRlXG4gKiBjb2RlKS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNsZWFyU2VydmluZ0VuZHBvaW50c0NhY2hlKGhvc3Q/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgY2FjaGUgPSBDYWNoZU1hbmFnZXIuZ2V0SW5zdGFuY2VTeW5jKCk7XG4gIGlmIChob3N0KSB7XG4gICAgY29uc3Qga2V5ID0gY2FjaGUuZ2VuZXJhdGVLZXkoW0NBQ0hFX0tFWV9OQU1FU1BBQ0UsIGhvc3RdLCBTSEFSRURfVVNFUl9LRVkpO1xuICAgIGF3YWl0IGNhY2hlLmRlbGV0ZShrZXkpO1xuICB9IGVsc2Uge1xuICAgIGF3YWl0IGNhY2hlLmNsZWFyKCk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXN1bHQgb2YgZnV6enktcmVzb2x2aW5nIGEgdXNlci1zdXBwbGllZCBtb2RlbCBuYW1lIGFnYWluc3QgdGhlIGxpdmVcbiAqIGVuZHBvaW50IGxpc3QuIGBzY29yZWAgaXMgRnVzZS5qcydzIGRpc3RhbmNlIChgMGAgaXMgZXhhY3QsIGAxYCBpcyBubyBtYXRjaCk7XG4gKiBgbWF0Y2hlZGAgaXMgYGZhbHNlYCB3aGVuIHRoZSBzY29yZSBleGNlZWRzIHRoZSBjb25maWd1cmVkIHRocmVzaG9sZCBzb1xuICogY2FsbGVycyBjYW4gZmFsbCBiYWNrIHRvIHRoZSBvcmlnaW5hbCBpbnB1dCAoRGF0YWJyaWNrcyB3aWxsIHRoZW4gcmV0dXJuIGFcbiAqIGNsZWFuIDQwNCkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb2x2ZWRNb2RlbCB7XG4gIG1vZGVsSWQ6IHN0cmluZztcbiAgbWF0Y2hlZDogYm9vbGVhbjtcbiAgc2NvcmU/OiBudW1iZXI7XG59XG5cbi8qKiBPcHRpb25zIGFjY2VwdGVkIGJ5IHtAbGluayByZXNvbHZlTW9kZWxJZH0gLyB7QGxpbmsgc2VhcmNoU2VydmluZ0VuZHBvaW50c30uICovXG5leHBvcnQgaW50ZXJmYWNlIFJlc29sdmVNb2RlbE9wdGlvbnMge1xuICAvKiogRnVzZS5qcyB0aHJlc2hvbGQgKDAgPSBleGFjdCwgMSA9IGFueXRoaW5nKS4gRGVmYXVsdCBgMC40YC4gKi9cbiAgdGhyZXNob2xkPzogbnVtYmVyO1xufVxuXG4vKiogQSBzZXJ2aW5nIGVuZHBvaW50IHBhaXJlZCB3aXRoIGl0cyBmdXp6eS1tYXRjaCBkaXN0YW5jZSBmb3IgYSBxdWVyeS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NvcmVkRW5kcG9pbnQge1xuICBlbmRwb2ludDogU2VydmluZ0VuZHBvaW50U3VtbWFyeTtcbiAgLyoqIEZ1c2UuanMgZGlzdGFuY2U6IGAwYCBpcyBleGFjdCwgYDFgIGlzIG5vIG1hdGNoLiAqL1xuICBzY29yZTogbnVtYmVyO1xufVxuXG4vKipcbiAqIEZ1enp5LXJhbmsgZW5kcG9pbnRzIGJ5IGhvdyBjbG9zZWx5IHRoZWlyIGBuYW1lYCBtYXRjaGVzIGBpbnB1dGAsIGJlc3RcbiAqIChsb3dlc3Qgc2NvcmUpIGZpcnN0LCBrZWVwaW5nIG9ubHkgdGhvc2Ugd2l0aGluIGB0aHJlc2hvbGRgOlxuICpcbiAqIDEuIEFuIGV4YWN0IG5hbWUgbWF0Y2ggc2hvcnQtY2lyY3VpdHMgdG8gYSBzaW5nbGUgYHNjb3JlOiAwYCByZXN1bHQuXG4gKiAyLiBPdGhlcndpc2UgdGhlIGlucHV0IGlzIHRva2VuaXplZCAoZGFzaGVzIC8gdW5kZXJzY29yZXMgLyBzcGFjZXMgYmVjb21lXG4gKiAgICBzZXBhcmF0b3JzKSBhbmQgZmVkIHRocm91Z2ggRnVzZS5qcyBleHRlbmRlZCBzZWFyY2gsIHdoaWNoIEFORC1zIGVhY2hcbiAqICAgIHRva2VuIHdpdGggZnV6enkgbWF0Y2hpbmcgZW5hYmxlZCAtIHRoZSBcInRva2VuaXplZCBmdXp6eSBtYXRjaFwiIGEgY2FsbGVyXG4gKiAgICByZWFjaGVzIGZvciB3aGVuIHRoZXkgdHlwZSBgXCJjbGF1ZGUgc29ubmV0XCJgIGluc3RlYWQgb2YgdGhlIGZ1bGwgZW5kcG9pbnRcbiAqICAgIG5hbWUuXG4gKlxuICogUmV0dXJucyBgW11gIGZvciBhbiBlbXB0eSBlbmRwb2ludCBsaXN0IG9yIHdoZW4gYGlucHV0YCB0b2tlbml6ZXMgdG8gbm90aGluZyxcbiAqIHNvIGNhbGxlcnMgZmFsbCBiYWNrIHRvIHRoZSByYXcgaW5wdXQgYW5kIGxldCBEYXRhYnJpY2tzIHN1cmZhY2UgYSBjbGVhbiA0MDQuXG4gKiBUaGlzIG11bHRpLXJlc3VsdCBjb3JlIGlzIHNoYXJlZCBieSB7QGxpbmsgcmVzb2x2ZU1vZGVsSWR9IChzaW5nbGUgYmVzdCkgYW5kXG4gKiB0aGUgcmFua2VkIGByYW5rTW9kZWxzYCBzZWxlY3Rvci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaFNlcnZpbmdFbmRwb2ludHMoXG4gIGlucHV0OiBzdHJpbmcsXG4gIGVuZHBvaW50czogcmVhZG9ubHkgU2VydmluZ0VuZHBvaW50U3VtbWFyeVtdLFxuICBvcHRpb25zOiBSZXNvbHZlTW9kZWxPcHRpb25zID0ge30sXG4pOiBTY29yZWRFbmRwb2ludFtdIHtcbiAgaWYgKGVuZHBvaW50cy5sZW5ndGggPT09IDApIHJldHVybiBbXTtcbiAgZm9yIChjb25zdCBlcCBvZiBlbmRwb2ludHMpIHtcbiAgICBpZiAoZXAubmFtZSA9PT0gaW5wdXQpIHJldHVybiBbeyBlbmRwb2ludDogZXAsIHNjb3JlOiAwIH1dO1xuICB9XG4gIGNvbnN0IHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkID8/IERFRkFVTFRfRlVaWllfVEhSRVNIT0xEO1xuICAvLyBGdXNlIDcuMyBoYXMgbm8gYnVpbHQtaW4gdG9rZW5pemUgaG9vazsgaW4gZXh0ZW5kZWQgc2VhcmNoLCBzcGFjZS1zZXBhcmF0ZWRcbiAgLy8gdG9rZW5zIGFyZSBBTkQtZWQgd2l0aCBmdXp6eSBtYXRjaGluZyBlbmFibGVkLiBXZSBsZWFuIG9uIHRoZSBzaGFyZWRcbiAgLy8gdG9rZW5pemVyIHNvIHRoZSBzcGxpdHRpbmcgcnVsZXMgc3RheSBjb25zaXN0ZW50IHdpdGggdGhlIHJlc3Qgb2YgdGhlIHRvb2xraXQuXG4gIGNvbnN0IHF1ZXJ5ID0gQXJyYXkuZnJvbShcbiAgICBzdHJpbmcudG9rZW5pemVXaXRoT3B0aW9ucyh7IGxvd2VyQ2FzZTogdHJ1ZSwgY2FtZWxDYXNlOiBmYWxzZSB9LCBpbnB1dCksXG4gICkuam9pbihcIiBcIik7XG4gIGlmICghcXVlcnkpIHJldHVybiBbXTtcbiAgY29uc3QgZnVzZSA9IG5ldyBGdXNlKGVuZHBvaW50cywge1xuICAgIGtleXM6IFtcIm5hbWVcIl0sXG4gICAgdGhyZXNob2xkLFxuICAgIGlnbm9yZUxvY2F0aW9uOiB0cnVlLFxuICAgIGluY2x1ZGVTY29yZTogdHJ1ZSxcbiAgICB1c2VFeHRlbmRlZFNlYXJjaDogdHJ1ZSxcbiAgICBpc0Nhc2VTZW5zaXRpdmU6IGZhbHNlLFxuICB9KTtcbiAgcmV0dXJuIGZ1c2VcbiAgICAuc2VhcmNoKHF1ZXJ5KVxuICAgIC5maWx0ZXIoKHIpID0+IChyLnNjb3JlID8/IDApIDw9IHRocmVzaG9sZClcbiAgICAubWFwKChyKSA9PiAoeyBlbmRwb2ludDogci5pdGVtLCBzY29yZTogci5zY29yZSA/PyAwIH0pKTtcbn1cblxuLyoqXG4gKiBTbmFwIGEgdXNlci1zdXBwbGllZCBtb2RlbCBuYW1lIHRvIHRoZSBzaW5nbGUgY2xvc2VzdCBjb25maWd1cmVkIHNlcnZpbmdcbiAqIGVuZHBvaW50IHZpYSB7QGxpbmsgc2VhcmNoU2VydmluZ0VuZHBvaW50c30uIFJldHVybnMgdGhlIGlucHV0IHVuY2hhbmdlZCB3aXRoXG4gKiBgbWF0Y2hlZDogZmFsc2VgIHdoZW4gbm90aGluZyBzY29yZXMgd2l0aGluIHRoZSB0aHJlc2hvbGQgKG9yIHRoZSBjYXRhbG9ndWVcbiAqIGlzIGVtcHR5KSwgc28gYSBkZWxpYmVyYXRlIG1vZGVsIGlkIGlzIG5ldmVyIHNpbGVudGx5IHJld3JpdHRlbiB0byBhXG4gKiBzaW1pbGFyLWxvb2tpbmcgbmVpZ2hib3VyIGFuZCB0aGUgdXBzdHJlYW0gY2FsbCBzdXJmYWNlcyB0aGUgY2Fub25pY2FsIDQwNC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVNb2RlbElkKFxuICBpbnB1dDogc3RyaW5nLFxuICBlbmRwb2ludHM6IHJlYWRvbmx5IFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXSxcbiAgb3B0aW9uczogUmVzb2x2ZU1vZGVsT3B0aW9ucyA9IHt9LFxuKTogUmVzb2x2ZWRNb2RlbCB7XG4gIGNvbnN0IFtiZXN0XSA9IHNlYXJjaFNlcnZpbmdFbmRwb2ludHMoaW5wdXQsIGVuZHBvaW50cywgb3B0aW9ucyk7XG4gIGlmIChiZXN0KSB7XG4gICAgcmV0dXJuIHsgbW9kZWxJZDogYmVzdC5lbmRwb2ludC5uYW1lLCBtYXRjaGVkOiB0cnVlLCBzY29yZTogYmVzdC5zY29yZSB9O1xuICB9XG4gIHJldHVybiB7IG1vZGVsSWQ6IGlucHV0LCBtYXRjaGVkOiBmYWxzZSB9O1xufVxuIl19
@@ -0,0 +1 @@
1
+ {"root":["../src/classes.ts","../src/fallback.ts","../src/invoke.ts","../src/resolve.ts","../src/serving.ts","../index.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -13,25 +13,29 @@
13
13
  "dependencies": {
14
14
  "@databricks/appkit": "^0.43.0",
15
15
  "fuse.js": "^7.4.2",
16
- "@dbx-tools/appkit": "0.3.44",
17
- "@dbx-tools/shared-core": "0.3.44",
18
- "@dbx-tools/shared-model": "0.3.44"
16
+ "@dbx-tools/shared-core": "0.4.1",
17
+ "@dbx-tools/shared-model": "0.4.1",
18
+ "@dbx-tools/appkit": "0.4.1"
19
19
  },
20
- "main": "index.ts",
20
+ "main": "./lib/index.js",
21
21
  "license": "UNLICENSED",
22
22
  "publishConfig": {
23
23
  "access": "public"
24
24
  },
25
- "version": "0.3.44",
26
- "types": "index.ts",
25
+ "version": "0.4.1",
26
+ "types": "./lib/index.d.ts",
27
27
  "type": "module",
28
28
  "exports": {
29
- ".": "./index.ts",
29
+ ".": {
30
+ "types": "./lib/index.d.ts",
31
+ "default": "./lib/index.js"
32
+ },
30
33
  "./package.json": "./package.json"
31
34
  },
32
35
  "files": [
33
36
  "index.ts",
34
- "src"
37
+ "src",
38
+ "lib"
35
39
  ],
36
40
  "dbxToolsConfig": {
37
41
  "tags": [