@dbx-tools/tunnel 0.6.123 → 0.6.124

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.
@@ -16,7 +16,9 @@
16
16
  *
17
17
  * @module
18
18
  */
19
- import type { Interceptor } from "@dbx-tools/appkit";
19
+ import type { Interceptor, InterceptorContext } from "@dbx-tools/appkit";
20
+ import { resolveFrpConfig } from "./frp.ts";
21
+ import { resolvePortrConfig } from "./portr.ts";
20
22
  /** Options for {@link tunnelInterceptor} (each also resolvable from env). */
21
23
  export interface TunnelInterceptorOptions {
22
24
  /** Tunnel clients to run. Env `DBX_TOOLS_TUNNEL_TRANSPORT`; defaults to `portr`. */
@@ -50,6 +52,13 @@ export interface TunnelInterceptorOptions {
50
52
  }
51
53
  /** Public tunnel clients supported by the interceptor and CLI. */
52
54
  export type TunnelTransport = "portr" | "frp" | "both";
55
+ interface TunnelAuxiliary {
56
+ stop(): void;
57
+ }
58
+ interface TunnelRuntime {
59
+ startPortr(config: NonNullable<ReturnType<typeof resolvePortrConfig>>): Promise<TunnelAuxiliary>;
60
+ startFrp(config: NonNullable<ReturnType<typeof resolveFrpConfig>>, ctx: InterceptorContext): Promise<TunnelAuxiliary>;
61
+ }
53
62
  /** Resolve and validate the tunnel transport selector. */
54
63
  export declare function resolveTunnelTransport(transport?: string): TunnelTransport;
55
64
  /**
@@ -67,4 +76,5 @@ export declare function resolveTunnelTransport(transport?: string): TunnelTransp
67
76
  * interceptor: tunnelInterceptor(),
68
77
  * });
69
78
  */
70
- export declare function tunnelInterceptor(options?: TunnelInterceptorOptions): Interceptor;
79
+ export declare function tunnelInterceptor(options?: TunnelInterceptorOptions, runtime?: TunnelRuntime): Interceptor;
80
+ export {};
@@ -21,12 +21,34 @@ import { installFrp, resolveFrpConfig, superviseFrp, writeFrpConfig } from "./fr
21
21
  import { installPortr, resolvePortrConfig, supervisePortr, writePortrConfig } from "./portr.js";
22
22
  import { startPathProxy } from "./path-proxy.js";
23
23
  const logger = log.logger("tunnel:interceptor");
24
+ const defaultRuntime = {
25
+ async startPortr(config) {
26
+ const portrEnv = await installPortr();
27
+ await writePortrConfig(config, portrEnv);
28
+ return supervisePortr(config, portrEnv);
29
+ },
30
+ async startFrp(config, ctx) {
31
+ const pathProxy = config.stripPrefix && config.path !== "/"
32
+ ? await startPathProxy(config.targetPort, config.path)
33
+ : undefined;
34
+ if (pathProxy) {
35
+ config.targetPort = pathProxy.port;
36
+ ctx.onLifecycle("shutdown", () => void pathProxy.close());
37
+ }
38
+ const frpEnv = await installFrp();
39
+ const configPath = await writeFrpConfig(config, frpEnv);
40
+ const supervisor = superviseFrp(config, frpEnv, configPath);
41
+ return {
42
+ stop() {
43
+ supervisor.stop();
44
+ void pathProxy?.close();
45
+ },
46
+ };
47
+ },
48
+ };
24
49
  /** Resolve and validate the tunnel transport selector. */
25
50
  export function resolveTunnelTransport(transport) {
26
- const resolved = transport ??
27
- process.env.DBX_TOOLS_TUNNEL_TRANSPORT ??
28
- process.env.TUNNEL_TRANSPORT ??
29
- "portr";
51
+ const resolved = transport ?? process.env.DBX_TOOLS_TUNNEL_TRANSPORT ?? process.env.TUNNEL_TRANSPORT ?? "portr";
30
52
  if (resolved === "portr" || resolved === "frp" || resolved === "both")
31
53
  return resolved;
32
54
  throw new TypeError(`invalid tunnel transport: ${resolved} (expected portr, frp, or both)`);
@@ -50,14 +72,14 @@ function resolvePublicPort(port) {
50
72
  * interceptor: tunnelInterceptor(),
51
73
  * });
52
74
  */
53
- export function tunnelInterceptor(options = {}) {
75
+ export function tunnelInterceptor(options = {}, runtime = defaultRuntime) {
54
76
  return async (ctx) => {
55
77
  if (ctx.env.databricksHost) {
56
78
  process.env.DATABRICKS_HOST ??= ctx.env.databricksHost;
57
79
  }
58
80
  const port = resolvePublicPort(options.port);
59
81
  const transport = resolveTunnelTransport(options.transport);
60
- const auxiliaries = [];
82
+ const initializers = [];
61
83
  if (transport === "portr" || transport === "both") {
62
84
  const portrConfig = resolvePortrConfig({
63
85
  publicDomain: options.publicDomain,
@@ -65,9 +87,7 @@ export function tunnelInterceptor(options = {}) {
65
87
  port,
66
88
  });
67
89
  if (portrConfig) {
68
- const portrEnv = await installPortr();
69
- await writePortrConfig(portrConfig, portrEnv);
70
- auxiliaries.push(supervisePortr(portrConfig, portrEnv));
90
+ initializers.push(runtime.startPortr(portrConfig));
71
91
  }
72
92
  else {
73
93
  logger.info("portr not configured (requires PORTR_TOKEN and TUNNEL_PUBLIC_DOMAIN)");
@@ -86,32 +106,38 @@ export function tunnelInterceptor(options = {}) {
86
106
  port,
87
107
  });
88
108
  if (frpConfig) {
89
- const pathProxy = frpConfig.stripPrefix && frpConfig.path !== "/"
90
- ? await startPathProxy(port, frpConfig.path)
91
- : undefined;
92
- if (pathProxy) {
93
- frpConfig.targetPort = pathProxy.port;
94
- ctx.onLifecycle("shutdown", () => void pathProxy.close());
95
- }
96
- const frpEnv = await installFrp();
97
- const configPath = await writeFrpConfig(frpConfig, frpEnv);
98
- auxiliaries.push(superviseFrp(frpConfig, frpEnv, configPath));
109
+ initializers.push(runtime.startFrp(frpConfig, ctx));
99
110
  }
100
111
  else {
101
112
  logger.info("frp not configured (requires TUNNEL_PUBLIC_DOMAIN)");
102
113
  }
103
114
  }
104
- if (!auxiliaries.length)
115
+ if (!initializers.length)
105
116
  return;
106
- ctx.onTeardown(() => {
107
- for (const auxiliary of auxiliaries)
108
- auxiliary.stop();
109
- });
110
- ctx.onLifecycle("shutdown", () => {
117
+ const auxiliaries = [];
118
+ let stopped = false;
119
+ const stop = () => {
120
+ stopped = true;
111
121
  for (const auxiliary of auxiliaries)
112
122
  auxiliary.stop();
123
+ };
124
+ ctx.onTeardown(stop);
125
+ ctx.onLifecycle("shutdown", stop);
126
+ void Promise.allSettled(initializers).then((results) => {
127
+ for (const result of results) {
128
+ if (result.status === "rejected") {
129
+ logger.error("tunnel failed to start", { error: result.reason });
130
+ continue;
131
+ }
132
+ if (stopped)
133
+ result.value.stop();
134
+ else
135
+ auxiliaries.push(result.value);
136
+ }
137
+ if (!stopped && auxiliaries.length)
138
+ logger.info(`tunnel bound: ${transport} -> :${port}`);
113
139
  });
114
- logger.info(`tunnel bound: ${transport} -> :${port}`);
140
+ logger.info(`tunnel initialization scheduled: ${transport} -> :${port}`);
115
141
  };
116
142
  }
117
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJjZXB0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBR0gsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsVUFBVSxFQUFFLGdCQUFnQixFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDdEYsT0FBTyxFQUFFLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDaEcsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRWpELE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsb0JBQW9CLENBQUMsQ0FBQztBQXFDaEQsMERBQTBEO0FBQzFELE1BQU0sVUFBVSxzQkFBc0IsQ0FBQyxTQUFrQjtJQUN2RCxNQUFNLFFBQVEsR0FDWixTQUFTO1FBQ1QsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEI7UUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0I7UUFDNUIsT0FBTyxDQUFDO0lBQ1YsSUFBSSxRQUFRLEtBQUssT0FBTyxJQUFJLFFBQVEsS0FBSyxLQUFLLElBQUksUUFBUSxLQUFLLE1BQU07UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUN2RixNQUFNLElBQUksU0FBUyxDQUFDLDZCQUE2QixRQUFRLGlDQUFpQyxDQUFDLENBQUM7QUFDOUYsQ0FBQztBQUVELHFGQUFxRjtBQUNyRixTQUFTLGlCQUFpQixDQUFDLElBQWE7SUFDdEMsT0FBTyxJQUFJLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLElBQUksSUFBSSxDQUFDO0FBQzFFLENBQUM7QUFFRDs7Ozs7Ozs7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SUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNO1lBQUUsT0FBTztRQUNoQyxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNsQixLQUFLLE1BQU0sU0FBUyxJQUFJLFdBQVc7Z0JBQUUsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hELENBQUMsQ0FBQyxDQUFDO1FBQ0gsR0FBRyxDQUFDLFdBQVcsQ0FBQyxVQUFVLEVBQUUsR0FBRyxFQUFFO1lBQy9CLEtBQUssTUFBTSxTQUFTLElBQUksV0FBVztnQkFBRSxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDeEQsQ0FBQyxDQUFDLENBQUM7UUFDSCxNQUFNLENBQUMsSUFBSSxDQUFDLGlCQUFpQixTQUFTLFFBQVEsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN4RCxDQUFDLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBgdHVubmVsSW50ZXJjZXB0b3IoKWAgLSB0aGUge0BsaW5rIEludGVyY2VwdG9yfSB0aGF0IGZyb250cyBhbiBhcHAgd2l0aCBhIHB1YmxpY1xuICogcG9ydHIgYW5kL29yIGZycCB0dW5uZWwsIGNvbnN1bWluZyB0aGUge0BsaW5rIEludGVyY2VwdG9yQ29udGV4dH0gYEBkYngtdG9vbHMvYXBwa2l0YCdzXG4gKiBgY3JlYXRlQXBwYCBoYW5kcyBpdC5cbiAqXG4gKiBUaGUgdHVubmVsIHJ1bnMgSU4tUFJPQ0VTUzogdGhlIEFQUCBpcyB0aGUgbWFpbiBwcm9jZXNzIGFuZCBoYW5kcyB0aGlzIGludGVyY2VwdG9yXG4gKiBpdHMgY29udGV4dCwgcmF0aGVyIHRoYW4gYSB3cmFwcGVyIHByb2Nlc3Mgc3Bhd25pbmcgdGhlIGFwcCBhcyBhIGNoaWxkLiBUaGVcbiAqIGludGVyY2VwdG9yIGFwcGxpZXMgdGhlIGNvbXB1dGVkIHdvcmtzcGFjZSBob3N0LCBpbnN0YWxscyBhbmQgbGF1bmNoZXMgcG9ydHIgb24gdGhlXG4gKiBhcHAncyBwdWJsaWMgcG9ydCwgYmluZHMgdGhlIGNoaWxkIHByb2Nlc3MgdG8gdGhlIGFwcCwgYW5kIHN0b3BzIHBvcnRyIGR1cmluZyBhblxuICogb3JkZXJseSBBcHBLaXQgc2h1dGRvd24uXG4gKlxuICogVGhlIHBhc3N3b3JkbGVzcyBHQVRFIGlzIGEgc2VwYXJhdGUgY29uY2VybjogaXQgaXMgdGhlIGBhdXRoR2F0ZWAgQXBwS2l0IHBsdWdpbixcbiAqIHdoaWNoIHJlZ2lzdGVycyB0aGUgbG9naW4gcm91dGVzICsgYSBnYXRpbmcgbWlkZGxld2FyZSBvbiB0aGUgYXBwJ3Mgb3duIHNlcnZlci5cbiAqIFJlZ2lzdGVyIGl0IGluIHRoZSBhcHAncyBgcGx1Z2luc2AgZm9yIGdhdGVkIHRyYWZmaWMuIFRoaXMgaW50ZXJjZXB0b3IgaXMgb25seVxuICogdGhlIHBvcnRyIGhhbGYgLSBcInVwZGF0ZSB0aGUgaG9zdCwgYmluZCBwb3J0clwiIC0gdGhlIHNtYWxsZXN0IHVzZWZ1bCB1bml0LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEludGVyY2VwdG9yLCBJbnRlcmNlcHRvckNvbnRleHQgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbmltcG9ydCB7IGxvZywgb2JqZWN0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGluc3RhbGxGcnAsIHJlc29sdmVGcnBDb25maWcsIHN1cGVydmlzZUZycCwgd3JpdGVGcnBDb25maWcgfSBmcm9tIFwiLi9mcnAudHNcIjtcbmltcG9ydCB7IGluc3RhbGxQb3J0ciwgcmVzb2x2ZVBvcnRyQ29uZmlnLCBzdXBlcnZpc2VQb3J0ciwgd3JpdGVQb3J0ckNvbmZpZyB9IGZyb20gXCIuL3BvcnRyLnRzXCI7XG5pbXBvcnQgeyBzdGFydFBhdGhQcm94eSB9IGZyb20gXCIuL3BhdGgtcHJveHkudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcInR1bm5lbDppbnRlcmNlcHRvclwiKTtcblxuLyoqIE9wdGlvbnMgZm9yIHtAbGluayB0dW5uZWxJbnRlcmNlcHRvcn0gKGVhY2ggYWxzbyByZXNvbHZhYmxlIGZyb20gZW52KS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHVubmVsSW50ZXJjZXB0b3JPcHRpb25zIHtcbiAgLyoqIFR1bm5lbCBjbGllbnRzIHRvIHJ1bi4gRW52IGBEQlhfVE9PTFNfVFVOTkVMX1RSQU5TUE9SVGA7IGRlZmF1bHRzIHRvIGBwb3J0cmAuICovXG4gIHRyYW5zcG9ydD86IFR1bm5lbFRyYW5zcG9ydDtcbiAgLyoqIFB1YmxpYyBob3N0IHRvIHNlcnZlIG9uLiBFbnYgYFRVTk5FTF9QVUJMSUNfRE9NQUlOYC4gKi9cbiAgcHVibGljRG9tYWluPzogc3RyaW5nO1xuICAvKiogcG9ydHIgc3ViZG9tYWluIChlbHNlIGRlcml2ZWQgZnJvbSB7QGxpbmsgcHVibGljRG9tYWlufSkuICovXG4gIHN1YmRvbWFpbj86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBQVUJMSUMgcG9ydCBwb3J0ciBmb3J3YXJkcyB0byAtIHRoZSBwb3J0IHRoZSBhcHAgaXRzZWxmIGxpc3RlbnMgb24uXG4gICAqIERlZmF1bHRzIHRvIHRoZSBEYXRhYnJpY2tzIEFwcHMgcnVudGltZSBjb250cmFjdCBgREFUQUJSSUNLU19BUFBfUE9SVGBcbiAgICogKHRoZW4gYDgwMDBgKSwgd2hpY2ggaXMgdGhlIHBvcnQgdGhlIHBsYXRmb3JtIHJvdXRlcyB0by5cbiAgICovXG4gIHBvcnQ/OiBudW1iZXI7XG4gIC8qKiBmcnBzIGNvbnRyb2wgaG9zdDsgZGVmYXVsdHMgdG8gdGhlIEZSUCBwdWJsaWMgZG9tYWluLiBFbnYgYEZSUF9TRVJWRVJgLiAqL1xuICBmcnBTZXJ2ZXI/OiBzdHJpbmc7XG4gIC8qKiBGUlAgcHVibGljIEhUVFAgaG9zdC4gRW52IGBUVU5ORUxfRlJQX1BVQkxJQ19ET01BSU5gLiAqL1xuICBmcnBQdWJsaWNEb21haW4/OiBzdHJpbmc7XG4gIC8qKiBmcnBzIGNvbnRyb2wgcG9ydC4gRW52IGBGUlBfU0VSVkVSX1BPUlRgOyBkZWZhdWx0cyB0byBgNDQzYC4gKi9cbiAgZnJwU2VydmVyUG9ydD86IG51bWJlcjtcbiAgLyoqIGZycGMgdHJhbnNwb3J0IHByb3RvY29sLiBFbnYgYEZSUF9QUk9UT0NPTGA7IGRlZmF1bHRzIHRvIGB3c3NgLiAqL1xuICBmcnBQcm90b2NvbD86IHN0cmluZztcbiAgLyoqIGZycHMgYXV0aCB0b2tlbi4gRW52IGBGUlBfVE9LRU5gIChvciBgVFVOTkVMX1RPS0VOYCkuICovXG4gIGZycFRva2VuPzogc3RyaW5nO1xuICAvKiogZnJwIHByb3h5IHJlZ2lzdHJhdGlvbiBuYW1lLiBFbnYgYEZSUF9QUk9YWV9OQU1FYC4gKi9cbiAgZnJwUHJveHlOYW1lPzogc3RyaW5nO1xuICAvKiogRlJQIHBhdGggbG9jYXRpb24uIEVudiBgRlJQX1BBVEhgOyBkZWZhdWx0cyB0byBgREFUQUJSSUNLU19BUFBfTkFNRWAuICovXG4gIGZycFBhdGg/OiBzdHJpbmc7XG4gIC8qKiBTdHJpcCB0aGUgRlJQIHBhdGggYmVmb3JlIGZvcndhcmRpbmcuIEVudiBgRlJQX1NUUklQX1BSRUZJWGA7IGRlZmF1bHRzIHRydWUgZm9yIG5vbi1yb290IHBhdGhzLiAqL1xuICBmcnBTdHJpcFByZWZpeD86IGJvb2xlYW47XG59XG5cbi8qKiBQdWJsaWMgdHVubmVsIGNsaWVudHMgc3VwcG9ydGVkIGJ5IHRoZSBpbnRlcmNlcHRvciBhbmQgQ0xJLiAqL1xuZXhwb3J0IHR5cGUgVHVubmVsVHJhbnNwb3J0ID0gXCJwb3J0clwiIHwgXCJmcnBcIiB8IFwiYm90aFwiO1xuXG4vKiogUmVzb2x2ZSBhbmQgdmFsaWRhdGUgdGhlIHR1bm5lbCB0cmFuc3BvcnQgc2VsZWN0b3IuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVR1bm5lbFRyYW5zcG9ydCh0cmFuc3BvcnQ/OiBzdHJpbmcpOiBUdW5uZWxUcmFuc3BvcnQge1xuICBjb25zdCByZXNvbHZlZCA9XG4gICAgdHJhbnNwb3J0ID8/XG4gICAgcHJvY2Vzcy5lbnYuREJYX1RPT0xTX1RVTk5FTF9UUkFOU1BPUlQgPz9cbiAgICBwcm9jZXNzLmVudi5UVU5ORUxfVFJBTlNQT1JUID8/XG4gICAgXCJwb3J0clwiO1xuICBpZiAocmVzb2x2ZWQgPT09IFwicG9ydHJcIiB8fCByZXNvbHZlZCA9PT0gXCJmcnBcIiB8fCByZXNvbHZlZCA9PT0gXCJib3RoXCIpIHJldHVybiByZXNvbHZlZDtcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihgaW52YWxpZCB0dW5uZWwgdHJhbnNwb3J0OiAke3Jlc29sdmVkfSAoZXhwZWN0ZWQgcG9ydHIsIGZycCwgb3IgYm90aClgKTtcbn1cblxuLyoqIFJlc29sdmUgdGhlIHB1YmxpYyBwb3J0IHBvcnRyIHNob3VsZCB0YXJnZXQ6IGV4cGxpY2l0LCBlbHNlIHRoZSBBcHBzIGNvbnRyYWN0LiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVB1YmxpY1BvcnQocG9ydD86IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBwb3J0ID8/IG9iamVjdC50b051bWJlcihwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0FQUF9QT1JUKSA/PyA4MDAwO1xufVxuXG4vKipcbiAqIEJ1aWxkIHRoZSB0dW5uZWwge0BsaW5rIEludGVyY2VwdG9yfS4gUGFzcyBpdCB0byBgY3JlYXRlQXBwKHsgaW50ZXJjZXB0b3IgfSlgLlxuICpcbiAqIEEgbm8tb3AgKGxvZ3MgYW5kIHJldHVybnMpIHdoZW4gbm9uZSBvZiB0aGUgc2VsZWN0ZWQgdHVubmVsIGNsaWVudHMgcmVzb2x2ZVxuICogdXNhYmxlIGNvbmZpZ3VyYXRpb24sIHNvIGFuIGFwcCBjYW4gcmVnaXN0ZXIgaXQgdW5jb25kaXRpb25hbGx5LlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgeyBhcHBraXQgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbiAqIGltcG9ydCB7IHR1bm5lbEludGVyY2VwdG9yIH0gZnJvbSBcIkBkYngtdG9vbHMvdHVubmVsXCI7XG4gKlxuICogYXdhaXQgYXBwa2l0LmNyZWF0ZUFwcCh7XG4gKiAgIHBsdWdpbnM6IFtzZXJ2ZXIoeyBob3N0LCBzdGF0aWNQYXRoIH0pXSxcbiAqICAgaW50ZXJjZXB0b3I6IHR1bm5lbEludGVyY2VwdG9yKCksXG4gKiB9KTtcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR1bm5lbEludGVyY2VwdG9yKG9wdGlvbnM6IFR1bm5lbEludGVyY2VwdG9yT3B0aW9ucyA9IHt9KTogSW50ZXJjZXB0b3Ige1xuICByZXR1cm4gYXN5bmMgKGN0eDogSW50ZXJjZXB0b3JDb250ZXh0KTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgaWYgKGN0eC5lbnYuZGF0YWJyaWNrc0hvc3QpIHtcbiAgICAgIHByb2Nlc3MuZW52LkRBVEFCUklDS1NfSE9TVCA/Pz0gY3R4LmVudi5kYXRhYnJpY2tzSG9zdDtcbiAgICB9XG5cbiAgICBjb25zdCBwb3J0ID0gcmVzb2x2ZVB1YmxpY1BvcnQob3B0aW9ucy5wb3J0KTtcbiAgICBjb25zdCB0cmFuc3BvcnQgPSByZXNvbHZlVHVubmVsVHJhbnNwb3J0KG9wdGlvbnMudHJhbnNwb3J0KTtcbiAgICBjb25zdCBhdXhpbGlhcmllczogQXJyYXk8eyBzdG9wKCk6IHZvaWQgfT4gPSBbXTtcbiAgICBpZiAodHJhbnNwb3J0ID09PSBcInBvcnRyXCIgfHwgdHJhbnNwb3J0ID09PSBcImJvdGhcIikge1xuICAgICAgY29uc3QgcG9ydHJDb25maWcgPSByZXNvbHZlUG9ydHJDb25maWcoe1xuICAgICAgICBwdWJsaWNEb21haW46IG9wdGlvbnMucHVibGljRG9tYWluLFxuICAgICAgICBzdWJkb21haW46IG9wdGlvbnMuc3ViZG9tYWluLFxuICAgICAgICBwb3J0LFxuICAgICAgfSk7XG4gICAgICBpZiAocG9ydHJDb25maWcpIHtcbiAgICAgICAgY29uc3QgcG9ydHJFbnYgPSBhd2FpdCBpbnN0YWxsUG9ydHIoKTtcbiAgICAgICAgYXdhaXQgd3JpdGVQb3J0ckNvbmZpZyhwb3J0ckNvbmZpZywgcG9ydHJFbnYpO1xuICAgICAgICBhdXhpbGlhcmllcy5wdXNoKHN1cGVydmlzZVBvcnRyKHBvcnRyQ29uZmlnLCBwb3J0ckVudikpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCJwb3J0ciBub3QgY29uZmlndXJlZCAocmVxdWlyZXMgUE9SVFJfVE9LRU4gYW5kIFRVTk5FTF9QVUJMSUNfRE9NQUlOKVwiKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRyYW5zcG9ydCA9PT0gXCJmcnBcIiB8fCB0cmFuc3BvcnQgPT09IFwiYm90aFwiKSB7XG4gICAgICBjb25zdCBmcnBDb25maWcgPSByZXNvbHZlRnJwQ29uZmlnKHtcbiAgICAgICAgcHVibGljRG9tYWluOiBvcHRpb25zLmZycFB1YmxpY0RvbWFpbixcbiAgICAgICAgc2VydmVyOiBvcHRpb25zLmZycFNlcnZlcixcbiAgICAgICAgc2VydmVyUG9ydDogb3B0aW9ucy5mcnBTZXJ2ZXJQb3J0LFxuICAgICAgICBwcm90b2NvbDogb3B0aW9ucy5mcnBQcm90b2NvbCxcbiAgICAgICAgdG9rZW46IG9wdGlvbnMuZnJwVG9rZW4sXG4gICAgICAgIHByb3h5TmFtZTogb3B0aW9ucy5mcnBQcm94eU5hbWUsXG4gICAgICAgIHBhdGg6IG9wdGlvbnMuZnJwUGF0aCxcbiAgICAgICAgc3RyaXBQcmVmaXg6IG9wdGlvbnMuZnJwU3RyaXBQcmVmaXgsXG4gICAgICAgIHBvcnQsXG4gICAgICB9KTtcbiAgICAgIGlmIChmcnBDb25maWcpIHtcbiAgICAgICAgY29uc3QgcGF0aFByb3h5ID1cbiAgICAgICAgICBmcnBDb25maWcuc3RyaXBQcmVmaXggJiYgZnJwQ29uZmlnLnBhdGggIT09IFwiL1wiXG4gICAgICAgICAgICA/IGF3YWl0IHN0YXJ0UGF0aFByb3h5KHBvcnQsIGZycENvbmZpZy5wYXRoKVxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChwYXRoUHJveHkpIHtcbiAgICAgICAgICBmcnBDb25maWcudGFyZ2V0UG9ydCA9IHBhdGhQcm94eS5wb3J0O1xuICAgICAgICAgIGN0eC5vbkxpZmVjeWNsZShcInNodXRkb3duXCIsICgpID0+IHZvaWQgcGF0aFByb3h5LmNsb3NlKCkpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZycEVudiA9IGF3YWl0IGluc3RhbGxGcnAoKTtcbiAgICAgICAgY29uc3QgY29uZmlnUGF0aCA9IGF3YWl0IHdyaXRlRnJwQ29uZmlnKGZycENvbmZpZywgZnJwRW52KTtcbiAgICAgICAgYXV4aWxpYXJpZXMucHVzaChzdXBlcnZpc2VGcnAoZnJwQ29uZmlnLCBmcnBFbnYsIGNvbmZpZ1BhdGgpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKFwiZnJwIG5vdCBjb25maWd1cmVkIChyZXF1aXJlcyBUVU5ORUxfUFVCTElDX0RPTUFJTilcIik7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICghYXV4aWxpYXJpZXMubGVuZ3RoKSByZXR1cm47XG4gICAgY3R4Lm9uVGVhcmRvd24oKCkgPT4ge1xuICAgICAgZm9yIChjb25zdCBhdXhpbGlhcnkgb2YgYXV4aWxpYXJpZXMpIGF1eGlsaWFyeS5zdG9wKCk7XG4gICAgfSk7XG4gICAgY3R4Lm9uTGlmZWN5Y2xlKFwic2h1dGRvd25cIiwgKCkgPT4ge1xuICAgICAgZm9yIChjb25zdCBhdXhpbGlhcnkgb2YgYXV4aWxpYXJpZXMpIGF1eGlsaWFyeS5zdG9wKCk7XG4gICAgfSk7XG4gICAgbG9nZ2VyLmluZm8oYHR1bm5lbCBib3VuZDogJHt0cmFuc3BvcnR9IC0+IDoke3BvcnR9YCk7XG4gIH07XG59XG4iXX0=
143
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJjZXB0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBR0gsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsVUFBVSxFQUFFLGdCQUFnQixFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDdEYsT0FBTyxFQUFFLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDaEcsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRWpELE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsb0JBQW9CLENBQUMsQ0FBQztBQWlEaEQsTUFBTSxjQUFjLEdBQWtCO0lBQ3BDLEtBQUssQ0FBQyxVQUFVLENBQUMsTUFBTTtRQUNyQixNQUFNLFFBQVEsR0FBRyxNQUFNLFlBQVksRUFBRSxDQUFDO1FBQ3RDLE1BQU0sZ0JBQWdCLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ3pDLE9BQU8sY0FBYyxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBQ0QsS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsR0FBRztRQUN4QixNQUFNLFNBQVMsR0FDYixNQUFNLENBQUMsV0FBVyxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssR0FBRztZQUN2QyxDQUFDLENBQUMsTUFBTSxjQUFjLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDO1lBQ3RELENBQUMsQ0FBQyxTQUFTLENBQUM7UUFDaEIsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNkLE1BQU0sQ0FBQyxVQUFVLEdBQUcsU0FB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RSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztvQkFDakUsU0FBUztnQkFDWCxDQUFDO2dCQUNELElBQUksT0FBTztvQkFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDOztvQkFDNUIsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdEMsQ0FBQztZQUNELElBQUksQ0FBQyxPQUFPLElBQUksV0FBVyxDQUFDLE1BQU07Z0JBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsU0FBUyxRQUFRLElBQUksRUFBRSxDQUFDLENBQUM7UUFDNUYsQ0FBQyxDQUFDLENBQUM7UUFDSCxNQUFNLENBQUMsSUFBSSxDQUFDLG9DQUFvQyxTQUFTLFFBQVEsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMzRSxDQUFDLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBgdHVubmVsSW50ZXJjZXB0b3IoKWAgLSB0aGUge0BsaW5rIEludGVyY2VwdG9yfSB0aGF0IGZyb250cyBhbiBhcHAgd2l0aCBhIHB1YmxpY1xuICogcG9ydHIgYW5kL29yIGZycCB0dW5uZWwsIGNvbnN1bWluZyB0aGUge0BsaW5rIEludGVyY2VwdG9yQ29udGV4dH0gYEBkYngtdG9vbHMvYXBwa2l0YCdzXG4gKiBgY3JlYXRlQXBwYCBoYW5kcyBpdC5cbiAqXG4gKiBUaGUgdHVubmVsIHJ1bnMgSU4tUFJPQ0VTUzogdGhlIEFQUCBpcyB0aGUgbWFpbiBwcm9jZXNzIGFuZCBoYW5kcyB0aGlzIGludGVyY2VwdG9yXG4gKiBpdHMgY29udGV4dCwgcmF0aGVyIHRoYW4gYSB3cmFwcGVyIHByb2Nlc3Mgc3Bhd25pbmcgdGhlIGFwcCBhcyBhIGNoaWxkLiBUaGVcbiAqIGludGVyY2VwdG9yIGFwcGxpZXMgdGhlIGNvbXB1dGVkIHdvcmtzcGFjZSBob3N0LCBpbnN0YWxscyBhbmQgbGF1bmNoZXMgcG9ydHIgb24gdGhlXG4gKiBhcHAncyBwdWJsaWMgcG9ydCwgYmluZHMgdGhlIGNoaWxkIHByb2Nlc3MgdG8gdGhlIGFwcCwgYW5kIHN0b3BzIHBvcnRyIGR1cmluZyBhblxuICogb3JkZXJseSBBcHBLaXQgc2h1dGRvd24uXG4gKlxuICogVGhlIHBhc3N3b3JkbGVzcyBHQVRFIGlzIGEgc2VwYXJhdGUgY29uY2VybjogaXQgaXMgdGhlIGBhdXRoR2F0ZWAgQXBwS2l0IHBsdWdpbixcbiAqIHdoaWNoIHJlZ2lzdGVycyB0aGUgbG9naW4gcm91dGVzICsgYSBnYXRpbmcgbWlkZGxld2FyZSBvbiB0aGUgYXBwJ3Mgb3duIHNlcnZlci5cbiAqIFJlZ2lzdGVyIGl0IGluIHRoZSBhcHAncyBgcGx1Z2luc2AgZm9yIGdhdGVkIHRyYWZmaWMuIFRoaXMgaW50ZXJjZXB0b3IgaXMgb25seVxuICogdGhlIHBvcnRyIGhhbGYgLSBcInVwZGF0ZSB0aGUgaG9zdCwgYmluZCBwb3J0clwiIC0gdGhlIHNtYWxsZXN0IHVzZWZ1bCB1bml0LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEludGVyY2VwdG9yLCBJbnRlcmNlcHRvckNvbnRleHQgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbmltcG9ydCB7IGxvZywgb2JqZWN0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGluc3RhbGxGcnAsIHJlc29sdmVGcnBDb25maWcsIHN1cGVydmlzZUZycCwgd3JpdGVGcnBDb25maWcgfSBmcm9tIFwiLi9mcnAudHNcIjtcbmltcG9ydCB7IGluc3RhbGxQb3J0ciwgcmVzb2x2ZVBvcnRyQ29uZmlnLCBzdXBlcnZpc2VQb3J0ciwgd3JpdGVQb3J0ckNvbmZpZyB9IGZyb20gXCIuL3BvcnRyLnRzXCI7XG5pbXBvcnQgeyBzdGFydFBhdGhQcm94eSB9IGZyb20gXCIuL3BhdGgtcHJveHkudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcInR1bm5lbDppbnRlcmNlcHRvclwiKTtcblxuLyoqIE9wdGlvbnMgZm9yIHtAbGluayB0dW5uZWxJbnRlcmNlcHRvcn0gKGVhY2ggYWxzbyByZXNvbHZhYmxlIGZyb20gZW52KS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHVubmVsSW50ZXJjZXB0b3JPcHRpb25zIHtcbiAgLyoqIFR1bm5lbCBjbGllbnRzIHRvIHJ1bi4gRW52IGBEQlhfVE9PTFNfVFVOTkVMX1RSQU5TUE9SVGA7IGRlZmF1bHRzIHRvIGBwb3J0cmAuICovXG4gIHRyYW5zcG9ydD86IFR1bm5lbFRyYW5zcG9ydDtcbiAgLyoqIFB1YmxpYyBob3N0IHRvIHNlcnZlIG9uLiBFbnYgYFRVTk5FTF9QVUJMSUNfRE9NQUlOYC4gKi9cbiAgcHVibGljRG9tYWluPzogc3RyaW5nO1xuICAvKiogcG9ydHIgc3ViZG9tYWluIChlbHNlIGRlcml2ZWQgZnJvbSB7QGxpbmsgcHVibGljRG9tYWlufSkuICovXG4gIHN1YmRvbWFpbj86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBQVUJMSUMgcG9ydCBwb3J0ciBmb3J3YXJkcyB0byAtIHRoZSBwb3J0IHRoZSBhcHAgaXRzZWxmIGxpc3RlbnMgb24uXG4gICAqIERlZmF1bHRzIHRvIHRoZSBEYXRhYnJpY2tzIEFwcHMgcnVudGltZSBjb250cmFjdCBgREFUQUJSSUNLU19BUFBfUE9SVGBcbiAgICogKHRoZW4gYDgwMDBgKSwgd2hpY2ggaXMgdGhlIHBvcnQgdGhlIHBsYXRmb3JtIHJvdXRlcyB0by5cbiAgICovXG4gIHBvcnQ/OiBudW1iZXI7XG4gIC8qKiBmcnBzIGNvbnRyb2wgaG9zdDsgZGVmYXVsdHMgdG8gdGhlIEZSUCBwdWJsaWMgZG9tYWluLiBFbnYgYEZSUF9TRVJWRVJgLiAqL1xuICBmcnBTZXJ2ZXI/OiBzdHJpbmc7XG4gIC8qKiBGUlAgcHVibGljIEhUVFAgaG9zdC4gRW52IGBUVU5ORUxfRlJQX1BVQkxJQ19ET01BSU5gLiAqL1xuICBmcnBQdWJsaWNEb21haW4/OiBzdHJpbmc7XG4gIC8qKiBmcnBzIGNvbnRyb2wgcG9ydC4gRW52IGBGUlBfU0VSVkVSX1BPUlRgOyBkZWZhdWx0cyB0byBgNDQzYC4gKi9cbiAgZnJwU2VydmVyUG9ydD86IG51bWJlcjtcbiAgLyoqIGZycGMgdHJhbnNwb3J0IHByb3RvY29sLiBFbnYgYEZSUF9QUk9UT0NPTGA7IGRlZmF1bHRzIHRvIGB3c3NgLiAqL1xuICBmcnBQcm90b2NvbD86IHN0cmluZztcbiAgLyoqIGZycHMgYXV0aCB0b2tlbi4gRW52IGBGUlBfVE9LRU5gIChvciBgVFVOTkVMX1RPS0VOYCkuICovXG4gIGZycFRva2VuPzogc3RyaW5nO1xuICAvKiogZnJwIHByb3h5IHJlZ2lzdHJhdGlvbiBuYW1lLiBFbnYgYEZSUF9QUk9YWV9OQU1FYC4gKi9cbiAgZnJwUHJveHlOYW1lPzogc3RyaW5nO1xuICAvKiogRlJQIHBhdGggbG9jYXRpb24uIEVudiBgRlJQX1BBVEhgOyBkZWZhdWx0cyB0byBgREFUQUJSSUNLU19BUFBfTkFNRWAuICovXG4gIGZycFBhdGg/OiBzdHJpbmc7XG4gIC8qKiBTdHJpcCB0aGUgRlJQIHBhdGggYmVmb3JlIGZvcndhcmRpbmcuIEVudiBgRlJQX1NUUklQX1BSRUZJWGA7IGRlZmF1bHRzIHRydWUgZm9yIG5vbi1yb290IHBhdGhzLiAqL1xuICBmcnBTdHJpcFByZWZpeD86IGJvb2xlYW47XG59XG5cbi8qKiBQdWJsaWMgdHVubmVsIGNsaWVudHMgc3VwcG9ydGVkIGJ5IHRoZSBpbnRlcmNlcHRvciBhbmQgQ0xJLiAqL1xuZXhwb3J0IHR5cGUgVHVubmVsVHJhbnNwb3J0ID0gXCJwb3J0clwiIHwgXCJmcnBcIiB8IFwiYm90aFwiO1xuXG5pbnRlcmZhY2UgVHVubmVsQXV4aWxpYXJ5IHtcbiAgc3RvcCgpOiB2b2lkO1xufVxuXG5pbnRlcmZhY2UgVHVubmVsUnVudGltZSB7XG4gIHN0YXJ0UG9ydHIoY29uZmlnOiBOb25OdWxsYWJsZTxSZXR1cm5UeXBlPHR5cGVvZiByZXNvbHZlUG9ydHJDb25maWc+Pik6IFByb21pc2U8VHVubmVsQXV4aWxpYXJ5PjtcbiAgc3RhcnRGcnAoXG4gICAgY29uZmlnOiBOb25OdWxsYWJsZTxSZXR1cm5UeXBlPHR5cGVvZiByZXNvbHZlRnJwQ29uZmlnPj4sXG4gICAgY3R4OiBJbnRlcmNlcHRvckNvbnRleHQsXG4gICk6IFByb21pc2U8VHVubmVsQXV4aWxpYXJ5Pjtcbn1cblxuY29uc3QgZGVmYXVsdFJ1bnRpbWU6IFR1bm5lbFJ1bnRpbWUgPSB7XG4gIGFzeW5jIHN0YXJ0UG9ydHIoY29uZmlnKSB7XG4gICAgY29uc3QgcG9ydHJFbnYgPSBhd2FpdCBpbnN0YWxsUG9ydHIoKTtcbiAgICBhd2FpdCB3cml0ZVBvcnRyQ29uZmlnKGNvbmZpZywgcG9ydHJFbnYpO1xuICAgIHJldHVybiBzdXBlcnZpc2VQb3J0cihjb25maWcsIHBvcnRyRW52KTtcbiAgfSxcbiAgYXN5bmMgc3RhcnRGcnAoY29uZmlnLCBjdHgpIHtcbiAgICBjb25zdCBwYXRoUHJveHkgPVxuICAgICAgY29uZmlnLnN0cmlwUHJlZml4ICYmIGNvbmZpZy5wYXRoICE9PSBcIi9cIlxuICAgICAgICA/IGF3YWl0IHN0YXJ0UGF0aFByb3h5KGNvbmZpZy50YXJnZXRQb3J0LCBjb25maWcucGF0aClcbiAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgaWYgKHBhdGhQcm94eSkge1xuICAgICAgY29uZmlnLnRhcmdldFBvcnQgPSBwYXRoUHJveHkucG9ydDtcbiAgICAgIGN0eC5vbkxpZmVjeWNsZShcInNodXRkb3duXCIsICgpID0+IHZvaWQgcGF0aFByb3h5LmNsb3NlKCkpO1xuICAgIH1cbiAgICBjb25zdCBmcnBFbnYgPSBhd2FpdCBpbnN0YWxsRnJwKCk7XG4gICAgY29uc3QgY29uZmlnUGF0aCA9IGF3YWl0IHdyaXRlRnJwQ29uZmlnKGNvbmZpZywgZnJwRW52KTtcbiAgICBjb25zdCBzdXBlcnZpc29yID0gc3VwZXJ2aXNlRnJwKGNvbmZpZywgZnJwRW52LCBjb25maWdQYXRoKTtcbiAgICByZXR1cm4ge1xuICAgICAgc3RvcCgpIHtcbiAgICAgICAgc3VwZXJ2aXNvci5zdG9wKCk7XG4gICAgICAgIHZvaWQgcGF0aFByb3h5Py5jbG9zZSgpO1xuICAgICAgfSxcbiAgICB9O1xuICB9LFxufTtcblxuLyoqIFJlc29sdmUgYW5kIHZhbGlkYXRlIHRoZSB0dW5uZWwgdHJhbnNwb3J0IHNlbGVjdG9yLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVUdW5uZWxUcmFuc3BvcnQodHJhbnNwb3J0Pzogc3RyaW5nKTogVHVubmVsVHJhbnNwb3J0IHtcbiAgY29uc3QgcmVzb2x2ZWQgPVxuICAgIHRyYW5zcG9ydCA/PyBwcm9jZXNzLmVudi5EQlhfVE9PTFNfVFVOTkVMX1RSQU5TUE9SVCA/PyBwcm9jZXNzLmVudi5UVU5ORUxfVFJBTlNQT1JUID8/IFwicG9ydHJcIjtcbiAgaWYgKHJlc29sdmVkID09PSBcInBvcnRyXCIgfHwgcmVzb2x2ZWQgPT09IFwiZnJwXCIgfHwgcmVzb2x2ZWQgPT09IFwiYm90aFwiKSByZXR1cm4gcmVzb2x2ZWQ7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoYGludmFsaWQgdHVubmVsIHRyYW5zcG9ydDogJHtyZXNvbHZlZH0gKGV4cGVjdGVkIHBvcnRyLCBmcnAsIG9yIGJvdGgpYCk7XG59XG5cbi8qKiBSZXNvbHZlIHRoZSBwdWJsaWMgcG9ydCBwb3J0ciBzaG91bGQgdGFyZ2V0OiBleHBsaWNpdCwgZWxzZSB0aGUgQXBwcyBjb250cmFjdC4gKi9cbmZ1bmN0aW9uIHJlc29sdmVQdWJsaWNQb3J0KHBvcnQ/OiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gcG9ydCA/PyBvYmplY3QudG9OdW1iZXIocHJvY2Vzcy5lbnYuREFUQUJSSUNLU19BUFBfUE9SVCkgPz8gODAwMDtcbn1cblxuLyoqXG4gKiBCdWlsZCB0aGUgdHVubmVsIHtAbGluayBJbnRlcmNlcHRvcn0uIFBhc3MgaXQgdG8gYGNyZWF0ZUFwcCh7IGludGVyY2VwdG9yIH0pYC5cbiAqXG4gKiBBIG5vLW9wIChsb2dzIGFuZCByZXR1cm5zKSB3aGVuIG5vbmUgb2YgdGhlIHNlbGVjdGVkIHR1bm5lbCBjbGllbnRzIHJlc29sdmVcbiAqIHVzYWJsZSBjb25maWd1cmF0aW9uLCBzbyBhbiBhcHAgY2FuIHJlZ2lzdGVyIGl0IHVuY29uZGl0aW9uYWxseS5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IHsgYXBwa2l0IH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG4gKiBpbXBvcnQgeyB0dW5uZWxJbnRlcmNlcHRvciB9IGZyb20gXCJAZGJ4LXRvb2xzL3R1bm5lbFwiO1xuICpcbiAqIGF3YWl0IGFwcGtpdC5jcmVhdGVBcHAoe1xuICogICBwbHVnaW5zOiBbc2VydmVyKHsgaG9zdCwgc3RhdGljUGF0aCB9KV0sXG4gKiAgIGludGVyY2VwdG9yOiB0dW5uZWxJbnRlcmNlcHRvcigpLFxuICogfSk7XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0dW5uZWxJbnRlcmNlcHRvcihcbiAgb3B0aW9uczogVHVubmVsSW50ZXJjZXB0b3JPcHRpb25zID0ge30sXG4gIHJ1bnRpbWU6IFR1bm5lbFJ1bnRpbWUgPSBkZWZhdWx0UnVudGltZSxcbik6IEludGVyY2VwdG9yIHtcbiAgcmV0dXJuIGFzeW5jIChjdHg6IEludGVyY2VwdG9yQ29udGV4dCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIGlmIChjdHguZW52LmRhdGFicmlja3NIb3N0KSB7XG4gICAgICBwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0hPU1QgPz89IGN0eC5lbnYuZGF0YWJyaWNrc0hvc3Q7XG4gICAgfVxuXG4gICAgY29uc3QgcG9ydCA9IHJlc29sdmVQdWJsaWNQb3J0KG9wdGlvbnMucG9ydCk7XG4gICAgY29uc3QgdHJhbnNwb3J0ID0gcmVzb2x2ZVR1bm5lbFRyYW5zcG9ydChvcHRpb25zLnRyYW5zcG9ydCk7XG4gICAgY29uc3QgaW5pdGlhbGl6ZXJzOiBBcnJheTxQcm9taXNlPFR1bm5lbEF1eGlsaWFyeT4+ID0gW107XG4gICAgaWYgKHRyYW5zcG9ydCA9PT0gXCJwb3J0clwiIHx8IHRyYW5zcG9ydCA9PT0gXCJib3RoXCIpIHtcbiAgICAgIGNvbnN0IHBvcnRyQ29uZmlnID0gcmVzb2x2ZVBvcnRyQ29uZmlnKHtcbiAgICAgICAgcHVibGljRG9tYWluOiBvcHRpb25zLnB1YmxpY0RvbWFpbixcbiAgICAgICAgc3ViZG9tYWluOiBvcHRpb25zLnN1YmRvbWFpbixcbiAgICAgICAgcG9ydCxcbiAgICAgIH0pO1xuICAgICAgaWYgKHBvcnRyQ29uZmlnKSB7XG4gICAgICAgIGluaXRpYWxpemVycy5wdXNoKHJ1bnRpbWUuc3RhcnRQb3J0cihwb3J0ckNvbmZpZykpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCJwb3J0ciBub3QgY29uZmlndXJlZCAocmVxdWlyZXMgUE9SVFJfVE9LRU4gYW5kIFRVTk5FTF9QVUJMSUNfRE9NQUlOKVwiKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRyYW5zcG9ydCA9PT0gXCJmcnBcIiB8fCB0cmFuc3BvcnQgPT09IFwiYm90aFwiKSB7XG4gICAgICBjb25zdCBmcnBDb25maWcgPSByZXNvbHZlRnJwQ29uZmlnKHtcbiAgICAgICAgcHVibGljRG9tYWluOiBvcHRpb25zLmZycFB1YmxpY0RvbWFpbixcbiAgICAgICAgc2VydmVyOiBvcHRpb25zLmZycFNlcnZlcixcbiAgICAgICAgc2VydmVyUG9ydDogb3B0aW9ucy5mcnBTZXJ2ZXJQb3J0LFxuICAgICAgICBwcm90b2NvbDogb3B0aW9ucy5mcnBQcm90b2NvbCxcbiAgICAgICAgdG9rZW46IG9wdGlvbnMuZnJwVG9rZW4sXG4gICAgICAgIHByb3h5TmFtZTogb3B0aW9ucy5mcnBQcm94eU5hbWUsXG4gICAgICAgIHBhdGg6IG9wdGlvbnMuZnJwUGF0aCxcbiAgICAgICAgc3RyaXBQcmVmaXg6IG9wdGlvbnMuZnJwU3RyaXBQcmVmaXgsXG4gICAgICAgIHBvcnQsXG4gICAgICB9KTtcbiAgICAgIGlmIChmcnBDb25maWcpIHtcbiAgICAgICAgaW5pdGlhbGl6ZXJzLnB1c2gocnVudGltZS5zdGFydEZycChmcnBDb25maWcsIGN0eCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCJmcnAgbm90IGNvbmZpZ3VyZWQgKHJlcXVpcmVzIFRVTk5FTF9QVUJMSUNfRE9NQUlOKVwiKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFpbml0aWFsaXplcnMubGVuZ3RoKSByZXR1cm47XG4gICAgY29uc3QgYXV4aWxpYXJpZXM6IFR1bm5lbEF1eGlsaWFyeVtdID0gW107XG4gICAgbGV0IHN0b3BwZWQgPSBmYWxzZTtcbiAgICBjb25zdCBzdG9wID0gKCkgPT4ge1xuICAgICAgc3RvcHBlZCA9IHRydWU7XG4gICAgICBmb3IgKGNvbnN0IGF1eGlsaWFyeSBvZiBhdXhpbGlhcmllcykgYXV4aWxpYXJ5LnN0b3AoKTtcbiAgICB9O1xuICAgIGN0eC5vblRlYXJkb3duKHN0b3ApO1xuICAgIGN0eC5vbkxpZmVjeWNsZShcInNodXRkb3duXCIsIHN0b3ApO1xuICAgIHZvaWQgUHJvbWlzZS5hbGxTZXR0bGVkKGluaXRpYWxpemVycykudGhlbigocmVzdWx0cykgPT4ge1xuICAgICAgZm9yIChjb25zdCByZXN1bHQgb2YgcmVzdWx0cykge1xuICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gXCJyZWplY3RlZFwiKSB7XG4gICAgICAgICAgbG9nZ2VyLmVycm9yKFwidHVubmVsIGZhaWxlZCB0byBzdGFydFwiLCB7IGVycm9yOiByZXN1bHQucmVhc29uIH0pO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdG9wcGVkKSByZXN1bHQudmFsdWUuc3RvcCgpO1xuICAgICAgICBlbHNlIGF1eGlsaWFyaWVzLnB1c2gocmVzdWx0LnZhbHVlKTtcbiAgICAgIH1cbiAgICAgIGlmICghc3RvcHBlZCAmJiBhdXhpbGlhcmllcy5sZW5ndGgpIGxvZ2dlci5pbmZvKGB0dW5uZWwgYm91bmQ6ICR7dHJhbnNwb3J0fSAtPiA6JHtwb3J0fWApO1xuICAgIH0pO1xuICAgIGxvZ2dlci5pbmZvKGB0dW5uZWwgaW5pdGlhbGl6YXRpb24gc2NoZWR1bGVkOiAke3RyYW5zcG9ydH0gLT4gOiR7cG9ydH1gKTtcbiAgfTtcbn1cbiJdfQ==
package/package.json CHANGED
@@ -23,16 +23,16 @@
23
23
  "typescript": "^5.9.3"
24
24
  },
25
25
  "peerDependencies": {
26
- "@dbx-tools/email": "0.6.123"
26
+ "@dbx-tools/email": "0.6.124"
27
27
  },
28
28
  "dependencies": {
29
29
  "@databricks/appkit": "^0.60.0",
30
- "@dbx-tools/appkit": "0.6.123",
31
- "@dbx-tools/auth": "0.6.123",
32
- "@dbx-tools/core": "0.6.123",
33
- "@dbx-tools/email": "0.6.123",
34
- "@dbx-tools/shared-auth": "0.6.123",
35
- "@dbx-tools/shared-core": "0.6.123",
30
+ "@dbx-tools/appkit": "0.6.124",
31
+ "@dbx-tools/auth": "0.6.124",
32
+ "@dbx-tools/core": "0.6.124",
33
+ "@dbx-tools/email": "0.6.124",
34
+ "@dbx-tools/shared-auth": "0.6.124",
35
+ "@dbx-tools/shared-core": "0.6.124",
36
36
  "http-proxy-3": "^1.23.1"
37
37
  },
38
38
  "main": "./lib/index.js",
@@ -49,7 +49,7 @@
49
49
  "./package.json": "./package.json"
50
50
  }
51
51
  },
52
- "version": "0.6.123",
52
+ "version": "0.6.124",
53
53
  "types": "./lib/index.d.ts",
54
54
  "type": "module",
55
55
  "exports": {
@@ -60,13 +60,49 @@ export interface TunnelInterceptorOptions {
60
60
  /** Public tunnel clients supported by the interceptor and CLI. */
61
61
  export type TunnelTransport = "portr" | "frp" | "both";
62
62
 
63
+ interface TunnelAuxiliary {
64
+ stop(): void;
65
+ }
66
+
67
+ interface TunnelRuntime {
68
+ startPortr(config: NonNullable<ReturnType<typeof resolvePortrConfig>>): Promise<TunnelAuxiliary>;
69
+ startFrp(
70
+ config: NonNullable<ReturnType<typeof resolveFrpConfig>>,
71
+ ctx: InterceptorContext,
72
+ ): Promise<TunnelAuxiliary>;
73
+ }
74
+
75
+ const defaultRuntime: TunnelRuntime = {
76
+ async startPortr(config) {
77
+ const portrEnv = await installPortr();
78
+ await writePortrConfig(config, portrEnv);
79
+ return supervisePortr(config, portrEnv);
80
+ },
81
+ async startFrp(config, ctx) {
82
+ const pathProxy =
83
+ config.stripPrefix && config.path !== "/"
84
+ ? await startPathProxy(config.targetPort, config.path)
85
+ : undefined;
86
+ if (pathProxy) {
87
+ config.targetPort = pathProxy.port;
88
+ ctx.onLifecycle("shutdown", () => void pathProxy.close());
89
+ }
90
+ const frpEnv = await installFrp();
91
+ const configPath = await writeFrpConfig(config, frpEnv);
92
+ const supervisor = superviseFrp(config, frpEnv, configPath);
93
+ return {
94
+ stop() {
95
+ supervisor.stop();
96
+ void pathProxy?.close();
97
+ },
98
+ };
99
+ },
100
+ };
101
+
63
102
  /** Resolve and validate the tunnel transport selector. */
64
103
  export function resolveTunnelTransport(transport?: string): TunnelTransport {
65
104
  const resolved =
66
- transport ??
67
- process.env.DBX_TOOLS_TUNNEL_TRANSPORT ??
68
- process.env.TUNNEL_TRANSPORT ??
69
- "portr";
105
+ transport ?? process.env.DBX_TOOLS_TUNNEL_TRANSPORT ?? process.env.TUNNEL_TRANSPORT ?? "portr";
70
106
  if (resolved === "portr" || resolved === "frp" || resolved === "both") return resolved;
71
107
  throw new TypeError(`invalid tunnel transport: ${resolved} (expected portr, frp, or both)`);
72
108
  }
@@ -91,7 +127,10 @@ function resolvePublicPort(port?: number): number {
91
127
  * interceptor: tunnelInterceptor(),
92
128
  * });
93
129
  */
94
- export function tunnelInterceptor(options: TunnelInterceptorOptions = {}): Interceptor {
130
+ export function tunnelInterceptor(
131
+ options: TunnelInterceptorOptions = {},
132
+ runtime: TunnelRuntime = defaultRuntime,
133
+ ): Interceptor {
95
134
  return async (ctx: InterceptorContext): Promise<void> => {
96
135
  if (ctx.env.databricksHost) {
97
136
  process.env.DATABRICKS_HOST ??= ctx.env.databricksHost;
@@ -99,7 +138,7 @@ export function tunnelInterceptor(options: TunnelInterceptorOptions = {}): Inter
99
138
 
100
139
  const port = resolvePublicPort(options.port);
101
140
  const transport = resolveTunnelTransport(options.transport);
102
- const auxiliaries: Array<{ stop(): void }> = [];
141
+ const initializers: Array<Promise<TunnelAuxiliary>> = [];
103
142
  if (transport === "portr" || transport === "both") {
104
143
  const portrConfig = resolvePortrConfig({
105
144
  publicDomain: options.publicDomain,
@@ -107,9 +146,7 @@ export function tunnelInterceptor(options: TunnelInterceptorOptions = {}): Inter
107
146
  port,
108
147
  });
109
148
  if (portrConfig) {
110
- const portrEnv = await installPortr();
111
- await writePortrConfig(portrConfig, portrEnv);
112
- auxiliaries.push(supervisePortr(portrConfig, portrEnv));
149
+ initializers.push(runtime.startPortr(portrConfig));
113
150
  } else {
114
151
  logger.info("portr not configured (requires PORTR_TOKEN and TUNNEL_PUBLIC_DOMAIN)");
115
152
  }
@@ -127,28 +164,31 @@ export function tunnelInterceptor(options: TunnelInterceptorOptions = {}): Inter
127
164
  port,
128
165
  });
129
166
  if (frpConfig) {
130
- const pathProxy =
131
- frpConfig.stripPrefix && frpConfig.path !== "/"
132
- ? await startPathProxy(port, frpConfig.path)
133
- : undefined;
134
- if (pathProxy) {
135
- frpConfig.targetPort = pathProxy.port;
136
- ctx.onLifecycle("shutdown", () => void pathProxy.close());
137
- }
138
- const frpEnv = await installFrp();
139
- const configPath = await writeFrpConfig(frpConfig, frpEnv);
140
- auxiliaries.push(superviseFrp(frpConfig, frpEnv, configPath));
167
+ initializers.push(runtime.startFrp(frpConfig, ctx));
141
168
  } else {
142
169
  logger.info("frp not configured (requires TUNNEL_PUBLIC_DOMAIN)");
143
170
  }
144
171
  }
145
- if (!auxiliaries.length) return;
146
- ctx.onTeardown(() => {
147
- for (const auxiliary of auxiliaries) auxiliary.stop();
148
- });
149
- ctx.onLifecycle("shutdown", () => {
172
+ if (!initializers.length) return;
173
+ const auxiliaries: TunnelAuxiliary[] = [];
174
+ let stopped = false;
175
+ const stop = () => {
176
+ stopped = true;
150
177
  for (const auxiliary of auxiliaries) auxiliary.stop();
178
+ };
179
+ ctx.onTeardown(stop);
180
+ ctx.onLifecycle("shutdown", stop);
181
+ void Promise.allSettled(initializers).then((results) => {
182
+ for (const result of results) {
183
+ if (result.status === "rejected") {
184
+ logger.error("tunnel failed to start", { error: result.reason });
185
+ continue;
186
+ }
187
+ if (stopped) result.value.stop();
188
+ else auxiliaries.push(result.value);
189
+ }
190
+ if (!stopped && auxiliaries.length) logger.info(`tunnel bound: ${transport} -> :${port}`);
151
191
  });
152
- logger.info(`tunnel bound: ${transport} -> :${port}`);
192
+ logger.info(`tunnel initialization scheduled: ${transport} -> :${port}`);
153
193
  };
154
194
  }