@dbx-tools/tunnel 0.6.104 → 0.6.106
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 +29 -18
- package/index.ts +3 -1
- package/lib/index.d.ts +3 -1
- package/lib/index.js +2 -1
- package/lib/src/frp.d.ts +44 -0
- package/lib/src/frp.js +118 -0
- package/lib/src/gate.d.ts +5 -5
- package/lib/src/gate.js +6 -5
- package/lib/src/interceptor.d.ts +22 -5
- package/lib/src/interceptor.js +58 -20
- package/lib/src/plugin.d.ts +5 -1
- package/lib/src/plugin.js +13 -4
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/frp.ts +183 -0
- package/src/gate.ts +10 -6
- package/src/interceptor.ts +71 -22
- package/src/plugin.ts +19 -4
package/README.md
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# @dbx-tools/tunnel
|
|
2
2
|
|
|
3
|
-
Front an app with a public tunnel and the passwordless
|
|
3
|
+
Front an app with a public Portr and/or FRP tunnel and the passwordless
|
|
4
4
|
[`@dbx-tools/auth`](../auth) gate, in-process.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
based on [upstream Portr](https://github.com/amalshaji/portr)
|
|
6
|
+
Supports the [SSE-enabled Portr fork](https://github.com/reggie-db/portr/releases/tag/v1.0.15-sse.2),
|
|
7
|
+
based on [upstream Portr](https://github.com/amalshaji/portr), plus
|
|
8
|
+
[FRP](https://github.com/fatedier/frp). Use this library
|
|
8
9
|
when an app needs to be reachable from outside its network - a stakeholder demo,
|
|
9
10
|
a webhook sender that has to reach a dev build, an OAuth redirect that cannot
|
|
10
11
|
point at `localhost` - without publishing the app to anyone who learns the URL.
|
|
@@ -14,8 +15,8 @@ platform-neutral.
|
|
|
14
15
|
|
|
15
16
|
The tunnel plugs into `@dbx-tools/appkit`'s `createApp` through its INTERCEPTOR
|
|
16
17
|
context: `createApp({ interceptor: tunnelInterceptor() })` applies the computed
|
|
17
|
-
`DATABRICKS_HOST`, launches
|
|
18
|
-
so the app and
|
|
18
|
+
`DATABRICKS_HOST`, launches the selected client(s) pointed at the app's public
|
|
19
|
+
port, and binds them so the app and tunnels live and die as one (signals pass
|
|
19
20
|
through, either death tears the pair down). The app is the process; the tunnel
|
|
20
21
|
rides along inside it. Access is granted per email address against an allow-list,
|
|
21
22
|
authenticated by Better Auth email OTP or a passkey; the gate itself is the
|
|
@@ -26,7 +27,7 @@ middleware on the app's OWN Express server (no separate proxy process).
|
|
|
26
27
|
|
|
27
28
|
- Consumed in-process via the `createApp` interceptor context - no wrapper CLI,
|
|
28
29
|
no separate process: `createApp({ interceptor: tunnelInterceptor() })`. A no-op
|
|
29
|
-
when
|
|
30
|
+
when the selected clients are not configured, so it is safe to register
|
|
30
31
|
unconditionally.
|
|
31
32
|
- Uses the shared email-template brand for the code email's color, font, and
|
|
32
33
|
logo. The displayed app name defaults to the dbx-tools brand and can be set
|
|
@@ -118,26 +119,24 @@ await appkit.createApp({
|
|
|
118
119
|
// Delivers the OTP codes; the gate reuses this shared transport.
|
|
119
120
|
email(),
|
|
120
121
|
// The OTP gate: login routes + a gating middleware on THIS server. Gates only
|
|
121
|
-
//
|
|
122
|
+
// public tunnel traffic; the platform front door passes
|
|
122
123
|
// through. Inert when no tunnel domain is configured.
|
|
123
124
|
authGate({}),
|
|
124
125
|
],
|
|
125
|
-
// Applies DATABRICKS_HOST
|
|
126
|
-
|
|
127
|
-
interceptor: tunnelInterceptor(),
|
|
126
|
+
// Applies DATABRICKS_HOST and launches FRP. Use "both" to launch Portr too.
|
|
127
|
+
interceptor: tunnelInterceptor({ transport: "frp" }),
|
|
128
128
|
});
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
Two pieces, one process: `tunnelInterceptor()` runs
|
|
132
|
-
app), and `authGate()` is the in-app gate.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
`TUNNEL_PUBLIC_DOMAIN` from the environment, so a deployment usually passes nothing.
|
|
131
|
+
Two pieces, one process: `tunnelInterceptor()` runs the selected tunnel clients
|
|
132
|
+
(children bound to the app), and `authGate()` is the in-app gate. Portr remains
|
|
133
|
+
the default. Set `transport: "frp"` or `DBX_TOOLS_TUNNEL_TRANSPORT=frp`; use `both` with
|
|
134
|
+
separate `TUNNEL_PUBLIC_DOMAIN` and `TUNNEL_FRP_PUBLIC_DOMAIN` hosts.
|
|
136
135
|
See [Use The Gate](#use-the-gate) for the gate on its own.
|
|
137
136
|
|
|
138
137
|
## Options
|
|
139
138
|
|
|
140
|
-
The interceptor reads
|
|
139
|
+
The interceptor reads tunnel wiring from the environment; the gate (the `authGate`
|
|
141
140
|
plugin) reads its own settings the same way, so a deployment configures both
|
|
142
141
|
without touching code.
|
|
143
142
|
|
|
@@ -152,6 +151,13 @@ without touching code.
|
|
|
152
151
|
| `TUNNEL_AUTH_SESSION_CUTOFF` | unset (no cutoff) |
|
|
153
152
|
| `TUNNEL_AUTH_LOGOUT_REDIRECT` | `/` (show login again) |
|
|
154
153
|
| `TUNNEL_PUBLIC_DOMAIN` | - (no tunnel when unset) |
|
|
154
|
+
| `TUNNEL_FRP_PUBLIC_DOMAIN` | - (no FRP tunnel when unset) |
|
|
155
|
+
| `DBX_TOOLS_TUNNEL_TRANSPORT` | `portr` |
|
|
156
|
+
| `FRP_SERVER` | FRP public domain |
|
|
157
|
+
| `FRP_SERVER_PORT` | `443` |
|
|
158
|
+
| `FRP_PROTOCOL` | `wss` |
|
|
159
|
+
| `FRP_TOKEN` | unset (no frps auth) |
|
|
160
|
+
| `FRP_PROXY_NAME` | public domain's first label |
|
|
155
161
|
| `TUNNEL_FORWARD_HEADERS` | the built-in `x-` allow-list |
|
|
156
162
|
| `TUNNEL_AUTH_JWT_SECRET` | an ephemeral per-process key |
|
|
157
163
|
|
|
@@ -162,7 +168,7 @@ The earlier unprefixed spellings - `AUTH_SUBJECT`, `AUTH_BRAND_NAME`,
|
|
|
162
168
|
`EMAIL_AUTH_ALLOW`, `PUBLIC_DOMAIN`, plus `TUNNEL_AUTH_SESSION_EPOCH` from before
|
|
163
169
|
the cutoff rename - are still read as deprecated aliases, with the `TUNNEL_` name
|
|
164
170
|
winning when both are set, so an existing deployment needs no coordinated rename.
|
|
165
|
-
`
|
|
171
|
+
`PORTR_*` and `FRP_*` keep their names: those namespaces belong to the clients
|
|
166
172
|
itself, as does `DATABRICKS_APP_PORT`, which the platform sets and the tunnel
|
|
167
173
|
honours.
|
|
168
174
|
|
|
@@ -367,11 +373,16 @@ RUN_LIVE_INSTALL_TEST=1 bun test packages/js/node/tunnel/test/portr-install.inte
|
|
|
367
373
|
|
|
368
374
|
The test installs into an isolated temporary home, runs `portr --version`, logs
|
|
369
375
|
the selected release and executable path, then removes the temporary directory.
|
|
376
|
+
The same command also discovers `frp-install.integration.test.ts`; it downloads
|
|
377
|
+
the pinned `frpc` release and verifies its exact version. On macOS the installer
|
|
378
|
+
applies an ad-hoc signature before version detection because the unsigned
|
|
379
|
+
upstream binary is otherwise terminated by the platform loader.
|
|
370
380
|
|
|
371
381
|
## Modules
|
|
372
382
|
|
|
373
383
|
- `interceptor` - `tunnelInterceptor()`, the `createApp` interceptor that applies
|
|
374
|
-
`DATABRICKS_HOST`, launches
|
|
384
|
+
`DATABRICKS_HOST`, launches Portr/FRP, and binds clients to the app.
|
|
385
|
+
- `frp` - frpc config resolution, pinned install, TOML rendering, and child launch.
|
|
375
386
|
- `plugin` - `authGate()`, authorization/delivery config, Better Auth
|
|
376
387
|
composition, and AppKit Lakebase discovery.
|
|
377
388
|
- `gate` - the login routes + gating middleware (`mountGate`, `isTunnelHost`):
|
package/index.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/tunnel";
|
|
6
6
|
export * as allowlist from "./src/allowlist.ts";
|
|
7
7
|
export * as codeEmail from "./src/code-email.ts";
|
|
8
|
+
export * as frp from "./src/frp.ts";
|
|
8
9
|
export * as gate from "./src/gate.ts";
|
|
9
10
|
export * as headers from "./src/headers.ts";
|
|
10
11
|
export * as interceptor from "./src/interceptor.ts";
|
|
@@ -14,11 +15,12 @@ export * as portr from "./src/portr.ts";
|
|
|
14
15
|
export * as sendCode from "./src/send-code.ts";
|
|
15
16
|
export * as signingKey from "./src/signing-key.ts";
|
|
16
17
|
export type { CodeCopy } from "./src/code-email.ts";
|
|
18
|
+
export type { FrpInstallOptions, FrpConfig } from "./src/frp.ts";
|
|
17
19
|
export { AUTH_PREFIX, UNAUTHORIZED_BODY } from "./src/gate.ts";
|
|
18
20
|
export type { GateOptions, GateAction } from "./src/gate.ts";
|
|
19
21
|
export { PROTECTED_HEADERS, DEFAULT_FORWARD_HEADERS } from "./src/headers.ts";
|
|
20
22
|
export type { HeaderPolicy } from "./src/headers.ts";
|
|
21
|
-
export type { TunnelInterceptorOptions } from "./src/interceptor.ts";
|
|
23
|
+
export type { TunnelInterceptorOptions, TunnelTransport } from "./src/interceptor.ts";
|
|
22
24
|
export type { LoginPageOptions } from "./src/login-page.ts";
|
|
23
25
|
export { AuthGatePlugin, authGate } from "./src/plugin.ts";
|
|
24
26
|
export type { AuthGateConfig, SendCodeOptions, ResolvedAuthGateConfig, AuthGateApi } from "./src/plugin.ts";
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare const PACKAGE_IDENTIFIER = "@dbx-tools/tunnel";
|
|
2
2
|
export * as allowlist from "./src/allowlist.ts";
|
|
3
3
|
export * as codeEmail from "./src/code-email.ts";
|
|
4
|
+
export * as frp from "./src/frp.ts";
|
|
4
5
|
export * as gate from "./src/gate.ts";
|
|
5
6
|
export * as headers from "./src/headers.ts";
|
|
6
7
|
export * as interceptor from "./src/interceptor.ts";
|
|
@@ -10,11 +11,12 @@ export * as portr from "./src/portr.ts";
|
|
|
10
11
|
export * as sendCode from "./src/send-code.ts";
|
|
11
12
|
export * as signingKey from "./src/signing-key.ts";
|
|
12
13
|
export type { CodeCopy } from "./src/code-email.ts";
|
|
14
|
+
export type { FrpInstallOptions, FrpConfig } from "./src/frp.ts";
|
|
13
15
|
export { AUTH_PREFIX, UNAUTHORIZED_BODY } from "./src/gate.ts";
|
|
14
16
|
export type { GateOptions, GateAction } from "./src/gate.ts";
|
|
15
17
|
export { PROTECTED_HEADERS, DEFAULT_FORWARD_HEADERS } from "./src/headers.ts";
|
|
16
18
|
export type { HeaderPolicy } from "./src/headers.ts";
|
|
17
|
-
export type { TunnelInterceptorOptions } from "./src/interceptor.ts";
|
|
19
|
+
export type { TunnelInterceptorOptions, TunnelTransport } from "./src/interceptor.ts";
|
|
18
20
|
export type { LoginPageOptions } from "./src/login-page.ts";
|
|
19
21
|
export { AuthGatePlugin, authGate } from "./src/plugin.ts";
|
|
20
22
|
export type { AuthGateConfig, SendCodeOptions, ResolvedAuthGateConfig, AuthGateApi } from "./src/plugin.ts";
|
package/lib/index.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/tunnel";
|
|
5
5
|
export * as allowlist from "./src/allowlist.js";
|
|
6
6
|
export * as codeEmail from "./src/code-email.js";
|
|
7
|
+
export * as frp from "./src/frp.js";
|
|
7
8
|
export * as gate from "./src/gate.js";
|
|
8
9
|
export * as headers from "./src/headers.js";
|
|
9
10
|
export * as interceptor from "./src/interceptor.js";
|
|
@@ -16,4 +17,4 @@ export { AUTH_PREFIX, UNAUTHORIZED_BODY } from "./src/gate.js";
|
|
|
16
17
|
export { PROTECTED_HEADERS, DEFAULT_FORWARD_HEADERS } from "./src/headers.js";
|
|
17
18
|
export { AuthGatePlugin, authGate } from "./src/plugin.js";
|
|
18
19
|
export { KEY_TTL_SECONDS } from "./src/signing-key.js";
|
|
19
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxtQkFBbUIsQ0FBQztBQUN0RCxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxTQUFTLE1BQU0scUJBQXFCLENBQUM7QUFDakQsT0FBTyxLQUFLLEdBQUcsTUFBTSxjQUFjLENBQUM7QUFDcEMsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEtBQUssV0FBVyxNQUFNLHNCQUFzQixDQUFDO0FBQ3BELE9BQU8sS0FBSyxTQUFTLE1BQU0scUJBQXFCLENBQUM7QUFDakQsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sS0FBSyxRQUFRLE1BQU0sb0JBQW9CLENBQUM7QUFDL0MsT0FBTyxLQUFLLFVBQVUsTUFBTSxzQkFBc0IsQ0FBQztBQUduRCxPQUFPLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRS9ELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBSTlFLE9BQU8sRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFHM0QsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gR0VORVJBVEVEIGJ5IHByb2plbiB3YXRjaCAtIERPIE5PVCBFRElULlxuLy8gUmVnZW5lcmF0ZWQgZnJvbSB0aGUgZXhwb3J0aW5nIG1vZHVsZXMgaW4gLi9zcmMuXG4vLyBIYW5kIGVkaXRzIGFyZSBvdmVyd3JpdHRlbiBvbiB0aGUgbmV4dCB3YXRjaDsgdGhpcyBmaWxlIGlzIHJlYWQtb25seS5cblxuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfSURFTlRJRklFUiA9IFwiQGRieC10b29scy90dW5uZWxcIjtcbmV4cG9ydCAqIGFzIGFsbG93bGlzdCBmcm9tIFwiLi9zcmMvYWxsb3dsaXN0LnRzXCI7XG5leHBvcnQgKiBhcyBjb2RlRW1haWwgZnJvbSBcIi4vc3JjL2NvZGUtZW1haWwudHNcIjtcbmV4cG9ydCAqIGFzIGZycCBmcm9tIFwiLi9zcmMvZnJwLnRzXCI7XG5leHBvcnQgKiBhcyBnYXRlIGZyb20gXCIuL3NyYy9nYXRlLnRzXCI7XG5leHBvcnQgKiBhcyBoZWFkZXJzIGZyb20gXCIuL3NyYy9oZWFkZXJzLnRzXCI7XG5leHBvcnQgKiBhcyBpbnRlcmNlcHRvciBmcm9tIFwiLi9zcmMvaW50ZXJjZXB0b3IudHNcIjtcbmV4cG9ydCAqIGFzIGxvZ2luUGFnZSBmcm9tIFwiLi9zcmMvbG9naW4tcGFnZS50c1wiO1xuZXhwb3J0ICogYXMgcGx1Z2luIGZyb20gXCIuL3NyYy9wbHVnaW4udHNcIjtcbmV4cG9ydCAqIGFzIHBvcnRyIGZyb20gXCIuL3NyYy9wb3J0ci50c1wiO1xuZXhwb3J0ICogYXMgc2VuZENvZGUgZnJvbSBcIi4vc3JjL3NlbmQtY29kZS50c1wiO1xuZXhwb3J0ICogYXMgc2lnbmluZ0tleSBmcm9tIFwiLi9zcmMvc2lnbmluZy1rZXkudHNcIjtcbmV4cG9ydCB0eXBlIHsgQ29kZUNvcHkgfSBmcm9tIFwiLi9zcmMvY29kZS1lbWFpbC50c1wiO1xuZXhwb3J0IHR5cGUgeyBGcnBJbnN0YWxsT3B0aW9ucywgRnJwQ29uZmlnIH0gZnJvbSBcIi4vc3JjL2ZycC50c1wiO1xuZXhwb3J0IHsgQVVUSF9QUkVGSVgsIFVOQVVUSE9SSVpFRF9CT0RZIH0gZnJvbSBcIi4vc3JjL2dhdGUudHNcIjtcbmV4cG9ydCB0eXBlIHsgR2F0ZU9wdGlvbnMsIEdhdGVBY3Rpb24gfSBmcm9tIFwiLi9zcmMvZ2F0ZS50c1wiO1xuZXhwb3J0IHsgUFJPVEVDVEVEX0hFQURFUlMsIERFRkFVTFRfRk9SV0FSRF9IRUFERVJTIH0gZnJvbSBcIi4vc3JjL2hlYWRlcnMudHNcIjtcbmV4cG9ydCB0eXBlIHsgSGVhZGVyUG9saWN5IH0gZnJvbSBcIi4vc3JjL2hlYWRlcnMudHNcIjtcbmV4cG9ydCB0eXBlIHsgVHVubmVsSW50ZXJjZXB0b3JPcHRpb25zLCBUdW5uZWxUcmFuc3BvcnQgfSBmcm9tIFwiLi9zcmMvaW50ZXJjZXB0b3IudHNcIjtcbmV4cG9ydCB0eXBlIHsgTG9naW5QYWdlT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9sb2dpbi1wYWdlLnRzXCI7XG5leHBvcnQgeyBBdXRoR2F0ZVBsdWdpbiwgYXV0aEdhdGUgfSBmcm9tIFwiLi9zcmMvcGx1Z2luLnRzXCI7XG5leHBvcnQgdHlwZSB7IEF1dGhHYXRlQ29uZmlnLCBTZW5kQ29kZU9wdGlvbnMsIFJlc29sdmVkQXV0aEdhdGVDb25maWcsIEF1dGhHYXRlQXBpIH0gZnJvbSBcIi4vc3JjL3BsdWdpbi50c1wiO1xuZXhwb3J0IHR5cGUgeyBQb3J0ckluc3RhbGxPcHRpb25zLCBQb3J0ckNvbmZpZyB9IGZyb20gXCIuL3NyYy9wb3J0ci50c1wiO1xuZXhwb3J0IHsgS0VZX1RUTF9TRUNPTkRTIH0gZnJvbSBcIi4vc3JjL3NpZ25pbmcta2V5LnRzXCI7XG5leHBvcnQgdHlwZSB7IFNpZ25pbmdLZXkgfSBmcm9tIFwiLi9zcmMvc2lnbmluZy1rZXkudHNcIjtcbiJdfQ==
|
package/lib/src/frp.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install and run an frp client (`frpc`) for a public HTTP tunnel.
|
|
3
|
+
*
|
|
4
|
+
* The defaults match the deployment shape used by inspire-mediamix: a single
|
|
5
|
+
* TLS-terminating host is both the WSS control endpoint and the HTTP custom
|
|
6
|
+
* domain. Callers may point `server` somewhere else when frps is exposed on a
|
|
7
|
+
* separate control host.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
12
|
+
/** Options for installing the frpc executable. */
|
|
13
|
+
export interface FrpInstallOptions {
|
|
14
|
+
/** Home directory containing `.frpc`; defaults to the OS home directory. */
|
|
15
|
+
homeDir?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Resolved frpc wiring, or `undefined` when no FRP tunnel is configured. */
|
|
18
|
+
export interface FrpConfig {
|
|
19
|
+
publicDomain: string;
|
|
20
|
+
server: string;
|
|
21
|
+
serverPort: number;
|
|
22
|
+
protocol: string;
|
|
23
|
+
token?: string;
|
|
24
|
+
proxyName: string;
|
|
25
|
+
port: number;
|
|
26
|
+
}
|
|
27
|
+
/** Resolve frpc config from the public domain and FRP-specific environment. */
|
|
28
|
+
export declare function resolveFrpConfig(opts: {
|
|
29
|
+
publicDomain?: string;
|
|
30
|
+
server?: string;
|
|
31
|
+
serverPort?: string | number;
|
|
32
|
+
protocol?: string;
|
|
33
|
+
token?: string;
|
|
34
|
+
proxyName?: string;
|
|
35
|
+
port: number;
|
|
36
|
+
}): FrpConfig | undefined;
|
|
37
|
+
/** GitHub release asset name for the current or supplied OS/architecture. */
|
|
38
|
+
export declare function frpAssetName(version: string, platform?: NodeJS.Platform, arch?: string): string;
|
|
39
|
+
/** Install frpc when absent and return the environment used by its process. */
|
|
40
|
+
export declare function installFrp(options?: FrpInstallOptions): Promise<NodeJS.ProcessEnv>;
|
|
41
|
+
/** Render `~/.frpc/frpc.toml` for the resolved tunnel. */
|
|
42
|
+
export declare function writeFrpConfig(resolved: FrpConfig, childEnv: NodeJS.ProcessEnv): Promise<string>;
|
|
43
|
+
/** Launch frpc as a child process (caller supervises and terminates it). */
|
|
44
|
+
export declare function startFrp(resolved: FrpConfig, childEnv: NodeJS.ProcessEnv, configPath: string): ReturnType<typeof spawn>;
|
package/lib/src/frp.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install and run an frp client (`frpc`) for a public HTTP tunnel.
|
|
3
|
+
*
|
|
4
|
+
* The defaults match the deployment shape used by inspire-mediamix: a single
|
|
5
|
+
* TLS-terminating host is both the WSS control endpoint and the HTTP custom
|
|
6
|
+
* domain. Callers may point `server` somewhere else when frps is exposed on a
|
|
7
|
+
* separate control host.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
12
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
13
|
+
import os from "node:os";
|
|
14
|
+
import { delimiter, join } from "node:path";
|
|
15
|
+
import { bin, config } from "@dbx-tools/core";
|
|
16
|
+
import { log } from "@dbx-tools/shared-core";
|
|
17
|
+
import { TUNNEL_CONFIG } from "./_config.js";
|
|
18
|
+
const logger = log.logger("tunnel:frp");
|
|
19
|
+
const FRP_VERSION = "0.68.1";
|
|
20
|
+
const FRP_RELEASE_URL = `https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}`;
|
|
21
|
+
function bareHost(value) {
|
|
22
|
+
if (!value)
|
|
23
|
+
return undefined;
|
|
24
|
+
const normalized = value.replace(/^https?:\/\//, "").split("/")[0]?.trim();
|
|
25
|
+
return normalized || undefined;
|
|
26
|
+
}
|
|
27
|
+
/** Resolve frpc config from the public domain and FRP-specific environment. */
|
|
28
|
+
export function resolveFrpConfig(opts) {
|
|
29
|
+
const publicDomain = bareHost(config.string(opts.publicDomain, ["FRP_PUBLIC_DOMAIN", "PUBLIC_DOMAIN"], TUNNEL_CONFIG));
|
|
30
|
+
if (!publicDomain)
|
|
31
|
+
return undefined;
|
|
32
|
+
const server = bareHost(config.string(opts.server, "FRP_SERVER")) ?? publicDomain;
|
|
33
|
+
const serverPort = config.port(opts.serverPort, "FRP_SERVER_PORT", 443);
|
|
34
|
+
const protocol = config.string(opts.protocol, "FRP_PROTOCOL") ?? "wss";
|
|
35
|
+
const token = config.string(opts.token, ["FRP_TOKEN", "TUNNEL_TOKEN"]);
|
|
36
|
+
const proxyName = config.string(opts.proxyName, "FRP_PROXY_NAME") ?? publicDomain.split(".")[0] ?? "app";
|
|
37
|
+
return {
|
|
38
|
+
publicDomain,
|
|
39
|
+
server,
|
|
40
|
+
serverPort,
|
|
41
|
+
protocol,
|
|
42
|
+
...(token ? { token } : {}),
|
|
43
|
+
proxyName,
|
|
44
|
+
port: opts.port,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** GitHub release asset name for the current or supplied OS/architecture. */
|
|
48
|
+
export function frpAssetName(version, platform = process.platform, arch = process.arch) {
|
|
49
|
+
const osName = platform === "darwin" ? "darwin" : platform === "linux" ? "linux" : undefined;
|
|
50
|
+
const archName = arch === "arm64" ? "arm64" : arch === "x64" ? "amd64" : undefined;
|
|
51
|
+
if (!osName || !archName) {
|
|
52
|
+
throw new Error(`frp has no supported release asset for ${platform}/${arch}`);
|
|
53
|
+
}
|
|
54
|
+
return `frp_${version}_${osName}_${archName}.tar.gz`;
|
|
55
|
+
}
|
|
56
|
+
function frpDownloadUrl() {
|
|
57
|
+
const assetName = frpAssetName(FRP_VERSION);
|
|
58
|
+
logger.info("installing frpc", { version: FRP_VERSION, asset: assetName });
|
|
59
|
+
return `${FRP_RELEASE_URL}/${assetName}`;
|
|
60
|
+
}
|
|
61
|
+
async function selectFrpc(source) {
|
|
62
|
+
const path = join(source, frpArchiveDirectory(), "frpc");
|
|
63
|
+
if (process.platform === "darwin") {
|
|
64
|
+
await new Promise((resolve, reject) => {
|
|
65
|
+
const signer = spawn("codesign", ["--force", "--sign", "-", path], { stdio: "ignore" });
|
|
66
|
+
signer.once("error", reject);
|
|
67
|
+
signer.once("exit", (code) => code === 0 ? resolve() : reject(new Error(`codesign exited with code ${code}`)));
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return path;
|
|
71
|
+
}
|
|
72
|
+
/** Install frpc when absent and return the environment used by its process. */
|
|
73
|
+
export async function installFrp(options = {}) {
|
|
74
|
+
const homeDir = options.homeDir ?? os.homedir();
|
|
75
|
+
const context = await bin.ensure("frpc", frpDownloadUrl, {
|
|
76
|
+
autoUnpackage: true,
|
|
77
|
+
homeDir,
|
|
78
|
+
minVersion: FRP_VERSION,
|
|
79
|
+
selector: ({ source }) => selectFrpc(source),
|
|
80
|
+
versionParser: ({ stdout, stderr }) => {
|
|
81
|
+
const version = bin.parseVersion({ stdout, stderr });
|
|
82
|
+
return version === FRP_VERSION ? version : undefined;
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
...process.env,
|
|
87
|
+
HOME: homeDir,
|
|
88
|
+
PATH: [context.binDir, process.env.PATH ?? ""].join(delimiter),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function frpArchiveDirectory(platform = process.platform, arch = process.arch) {
|
|
92
|
+
return frpAssetName(FRP_VERSION, platform, arch).replace(/\.tar\.gz$/, "");
|
|
93
|
+
}
|
|
94
|
+
function tomlString(value) {
|
|
95
|
+
return JSON.stringify(value);
|
|
96
|
+
}
|
|
97
|
+
/** Render `~/.frpc/frpc.toml` for the resolved tunnel. */
|
|
98
|
+
export async function writeFrpConfig(resolved, childEnv) {
|
|
99
|
+
const directory = join(childEnv.HOME ?? os.homedir(), ".frpc");
|
|
100
|
+
const path = join(directory, "frpc.toml");
|
|
101
|
+
await mkdir(directory, { recursive: true });
|
|
102
|
+
const lines = [
|
|
103
|
+
`serverAddr = ${tomlString(resolved.server)}`,
|
|
104
|
+
`serverPort = ${resolved.serverPort}`,
|
|
105
|
+
`transport.protocol = ${tomlString(resolved.protocol)}`,
|
|
106
|
+
];
|
|
107
|
+
if (resolved.token)
|
|
108
|
+
lines.push(`auth.token = ${tomlString(resolved.token)}`);
|
|
109
|
+
lines.push("", "[[proxies]]", `name = ${tomlString(resolved.proxyName)}`, 'type = "http"', `localPort = ${resolved.port}`, `customDomains = [${tomlString(resolved.publicDomain)}]`, "");
|
|
110
|
+
await writeFile(path, lines.join("\n"));
|
|
111
|
+
return path;
|
|
112
|
+
}
|
|
113
|
+
/** Launch frpc as a child process (caller supervises and terminates it). */
|
|
114
|
+
export function startFrp(resolved, childEnv, configPath) {
|
|
115
|
+
logger.info(`frpc tunneling https://${resolved.publicDomain} -> :${resolved.port}`);
|
|
116
|
+
return spawn("frpc", ["-c", configPath], { env: childEnv, stdio: "inherit" });
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ZycC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7O0dBU0c7QUFFSCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDM0MsT0FBTyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDekIsT0FBTyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFNUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUU3QyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBQ3hDLE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQztBQUM3QixNQUFNLGVBQWUsR0FBRyxzREFBc0QsV0FBVyxFQUFFLENBQUM7QUFtQjVGLFNBQVMsUUFBUSxDQUFDLEtBQXlCO0lBQ3pDLElBQUksQ0FBQyxLQUFLO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDN0IsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDO0lBQzNFLE9BQU8sVUFBVSxJQUFJLFNBQVMsQ0FBQztBQUNqQyxDQUFDO0FBRUQsK0VBQStFO0FBQy9FLE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxJQVFoQztJQUNDLE1BQU0sWUFBWSxHQUFHLFFBQVEsQ0FDM0IsTUFBTSxDQUFDLE1BQU0sQ0FDWCxJQUFJLENBQUMs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LENBQUMsS0FBSztRQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLFVBQVUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzdFLEtBQUssQ0FBQyxJQUFJLENBQ1IsRUFBRSxFQUNGLGFBQWEsRUFDYixVQUFVLFVBQVUsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFDMUMsZUFBZSxFQUNmLGVBQWUsUUFBUSxDQUFDLElBQUksRUFBRSxFQUM5QixvQkFBb0IsVUFBVSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUN4RCxFQUFFLENBQ0gsQ0FBQztJQUNGLE1BQU0sU0FBUyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDeEMsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsNEVBQTRFO0FBQzVFLE1BQU0sVUFBVSxRQUFRLENBQ3RCLFFBQW1CLEVBQ25CLFFBQTJCLEVBQzNCLFVBQWtCO0lBRWxCLE1BQU0sQ0FBQyxJQUFJLENBQUMsMEJBQTBCLFFBQVEsQ0FBQyxZQUFZLFFBQVEsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDcEYsT0FBTyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztBQUNoRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBJbnN0YWxsIGFuZCBydW4gYW4gZnJwIGNsaWVudCAoYGZycGNgKSBmb3IgYSBwdWJsaWMgSFRUUCB0dW5uZWwuXG4gKlxuICogVGhlIGRlZmF1bHRzIG1hdGNoIHRoZSBkZXBsb3ltZW50IHNoYXBlIHVzZWQgYnkgaW5zcGlyZS1tZWRpYW1peDogYSBzaW5nbGVcbiAqIFRMUy10ZXJtaW5hdGluZyBob3N0IGlzIGJvdGggdGhlIFdTUyBjb250cm9sIGVuZHBvaW50IGFuZCB0aGUgSFRUUCBjdXN0b21cbiAqIGRvbWFpbi4gQ2FsbGVycyBtYXkgcG9pbnQgYHNlcnZlcmAgc29tZXdoZXJlIGVsc2Ugd2hlbiBmcnBzIGlzIGV4cG9zZWQgb24gYVxuICogc2VwYXJhdGUgY29udHJvbCBob3N0LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBzcGF3biB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IG1rZGlyLCB3cml0ZUZpbGUgfSBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiO1xuaW1wb3J0IG9zIGZyb20gXCJub2RlOm9zXCI7XG5pbXBvcnQgeyBkZWxpbWl0ZXIsIGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5cbmltcG9ydCB7IGJpbiwgY29uZmlnIH0gZnJvbSBcIkBkYngtdG9vbHMvY29yZVwiO1xuaW1wb3J0IHsgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IFRVTk5FTF9DT05GSUcgfSBmcm9tIFwiLi9fY29uZmlnLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJ0dW5uZWw6ZnJwXCIpO1xuY29uc3QgRlJQX1ZFUlNJT04gPSBcIjAuNjguMVwiO1xuY29uc3QgRlJQX1JFTEVBU0VfVVJMID0gYGh0dHBzOi8vZ2l0aHViLmNvbS9mYXRlZGllci9mcnAvcmVsZWFzZXMvZG93bmxvYWQvdiR7RlJQX1ZFUlNJT059YDtcblxuLyoqIE9wdGlvbnMgZm9yIGluc3RhbGxpbmcgdGhlIGZycGMgZXhlY3V0YWJsZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRnJwSW5zdGFsbE9wdGlvbnMge1xuICAvKiogSG9tZSBkaXJlY3RvcnkgY29udGFpbmluZyBgLmZycGNgOyBkZWZhdWx0cyB0byB0aGUgT1MgaG9tZSBkaXJlY3RvcnkuICovXG4gIGhvbWVEaXI/OiBzdHJpbmc7XG59XG5cbi8qKiBSZXNvbHZlZCBmcnBjIHdpcmluZywgb3IgYHVuZGVmaW5lZGAgd2hlbiBubyBGUlAgdHVubmVsIGlzIGNvbmZpZ3VyZWQuICovXG5leHBvcnQgaW50ZXJmYWNlIEZycENvbmZpZyB7XG4gIHB1YmxpY0RvbWFpbjogc3RyaW5nO1xuICBzZXJ2ZXI6IHN0cmluZztcbiAgc2VydmVyUG9ydDogbnVtYmVyO1xuICBwcm90b2NvbDogc3RyaW5nO1xuICB0b2tlbj86IHN0cmluZztcbiAgcHJveHlOYW1lOiBzdHJpbmc7XG4gIHBvcnQ6IG51bWJlcjtcbn1cblxuZnVuY3Rpb24gYmFyZUhvc3QodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICghdmFsdWUpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSB2YWx1ZS5yZXBsYWNlKC9eaHR0cHM/OlxcL1xcLy8sIFwiXCIpLnNwbGl0KFwiL1wiKVswXT8udHJpbSgpO1xuICByZXR1cm4gbm9ybWFsaXplZCB8fCB1bmRlZmluZWQ7XG59XG5cbi8qKiBSZXNvbHZlIGZycGMgY29uZmlnIGZyb20gdGhlIHB1YmxpYyBkb21haW4gYW5kIEZSUC1zcGVjaWZpYyBlbnZpcm9ubWVudC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlRnJwQ29uZmlnKG9wdHM6IHtcbiAgcHVibGljRG9tYWluPzogc3RyaW5nO1xuICBzZXJ2ZXI/OiBzdHJpbmc7XG4gIHNlcnZlclBvcnQ/OiBzdHJpbmcgfCBudW1iZXI7XG4gIHByb3RvY29sPzogc3RyaW5nO1xuICB0b2tlbj86IHN0cmluZztcbiAgcHJveHlOYW1lPzogc3RyaW5nO1xuICBwb3J0OiBudW1iZXI7XG59KTogRnJwQ29uZmlnIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcHVibGljRG9tYWluID0gYmFyZUhvc3QoXG4gICAgY29uZmlnLnN0cmluZyhcbiAgICAgIG9wdHMucHVibGljRG9tYWluLFxuICAgICAgW1wiRlJQX1BVQkxJQ19ET01BSU5cIiwgXCJQVUJMSUNfRE9NQUlOXCJdLFxuICAgICAgVFVOTkVMX0NPTkZJRyxcbiAgICApLFxuICApO1xuICBpZiAoIXB1YmxpY0RvbWFpbikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3Qgc2VydmVyID0gYmFyZUhvc3QoY29uZmlnLnN0cmluZyhvcHRzLnNlcnZlciwgXCJGUlBfU0VSVkVSXCIpKSA/PyBwdWJsaWNEb21haW47XG4gIGNvbnN0IHNlcnZlclBvcnQgPSBjb25maWcucG9ydChvcHRzLnNlcnZlclBvcnQsIFwiRlJQX1NFUlZFUl9QT1JUXCIsIDQ0Myk7XG4gIGNvbnN0IHByb3RvY29sID0gY29uZmlnLnN0cmluZyhvcHRzLnByb3RvY29sLCBcIkZSUF9QUk9UT0NPTFwiKSA/PyBcIndzc1wiO1xuICBjb25zdCB0b2tlbiA9IGNvbmZpZy5zdHJpbmcob3B0cy50b2tlbiwgW1wiRlJQX1RPS0VOXCIsIFwiVFVOTkVMX1RPS0VOXCJdKTtcbiAgY29uc3QgcHJveHlOYW1lID1cbiAgICBjb25maWcuc3RyaW5nKG9wdHMucHJveHlOYW1lLCBcIkZSUF9QUk9YWV9OQU1FXCIpID8/IHB1YmxpY0RvbWFpbi5zcGxpdChcIi5cIilbMF0gPz8gXCJhcHBcIjtcbiAgcmV0dXJuIHtcbiAgICBwdWJsaWNEb21haW4sXG4gICAgc2VydmVyLFxuICAgIHNlcnZlclBvcnQsXG4gICAgcHJvdG9jb2wsXG4gICAgLi4uKHRva2VuID8geyB0b2tlbiB9IDoge30pLFxuICAgIHByb3h5TmFtZSxcbiAgICBwb3J0OiBvcHRzLnBvcnQsXG4gIH07XG59XG5cbi8qKiBHaXRIdWIgcmVsZWFzZSBhc3NldCBuYW1lIGZvciB0aGUgY3VycmVudCBvciBzdXBwbGllZCBPUy9hcmNoaXRlY3R1cmUuICovXG5leHBvcnQgZnVuY3Rpb24gZnJwQXNzZXROYW1lKFxuICB2ZXJzaW9uOiBzdHJpbmcsXG4gIHBsYXRmb3JtOiBOb2RlSlMuUGxhdGZvcm0gPSBwcm9jZXNzLnBsYXRmb3JtLFxuICBhcmNoOiBzdHJpbmcgPSBwcm9jZXNzLmFyY2gsXG4pOiBzdHJpbmcge1xuICBjb25zdCBvc05hbWUgPSBwbGF0Zm9ybSA9PT0gXCJkYXJ3aW5cIiA/IFwiZGFyd2luXCIgOiBwbGF0Zm9ybSA9PT0gXCJsaW51eFwiID8gXCJsaW51eFwiIDogdW5kZWZpbmVkO1xuICBjb25zdCBhcmNoTmFtZSA9IGFyY2ggPT09IFwiYXJtNjRcIiA/IFwiYXJtNjRcIiA6IGFyY2ggPT09IFwieDY0XCIgPyBcImFtZDY0XCIgOiB1bmRlZmluZWQ7XG4gIGlmICghb3NOYW1lIHx8ICFhcmNoTmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgZnJwIGhhcyBubyBzdXBwb3J0ZWQgcmVsZWFzZSBhc3NldCBmb3IgJHtwbGF0Zm9ybX0vJHthcmNofWApO1xuICB9XG4gIHJldHVybiBgZnJwXyR7dmVyc2lvbn1fJHtvc05hbWV9XyR7YXJjaE5hbWV9LnRhci5nemA7XG59XG5cbmZ1bmN0aW9uIGZycERvd25sb2FkVXJsKCk6IHN0cmluZyB7XG4gIGNvbnN0IGFzc2V0TmFtZSA9IGZycEFzc2V0TmFtZShGUlBfVkVSU0lPTik7XG4gIGxvZ2dlci5pbmZvKFwiaW5zdGFsbGluZyBmcnBjXCIsIHsgdmVyc2lvbjogRlJQX1ZFUlNJT04sIGFzc2V0OiBhc3NldE5hbWUgfSk7XG4gIHJldHVybiBgJHtGUlBfUkVMRUFTRV9VUkx9LyR7YXNzZXROYW1lfWA7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNlbGVjdEZycGMoc291cmNlOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBwYXRoID0gam9pbihzb3VyY2UsIGZycEFyY2hpdmVEaXJlY3RvcnkoKSwgXCJmcnBjXCIpO1xuICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gXCJkYXJ3aW5cIikge1xuICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNpZ25lciA9IHNwYXduKFwiY29kZXNpZ25cIiwgW1wiLS1mb3JjZVwiLCBcIi0tc2lnblwiLCBcIi1cIiwgcGF0aF0sIHsgc3RkaW86IFwiaWdub3JlXCIgfSk7XG4gICAgICBzaWduZXIub25jZShcImVycm9yXCIsIHJlamVjdCk7XG4gICAgICBzaWduZXIub25jZShcImV4aXRcIiwgKGNvZGUpID0+XG4gICAgICAgIGNvZGUgPT09IDAgPyByZXNvbHZlKCkgOiByZWplY3QobmV3IEVycm9yKGBjb2Rlc2lnbiBleGl0ZWQgd2l0aCBjb2RlICR7Y29kZX1gKSksXG4gICAgICApO1xuICAgIH0pO1xuICB9XG4gIHJldHVybiBwYXRoO1xufVxuXG4vKiogSW5zdGFsbCBmcnBjIHdoZW4gYWJzZW50IGFuZCByZXR1cm4gdGhlIGVudmlyb25tZW50IHVzZWQgYnkgaXRzIHByb2Nlc3MuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW5zdGFsbEZycChvcHRpb25zOiBGcnBJbnN0YWxsT3B0aW9ucyA9IHt9KTogUHJvbWlzZTxOb2RlSlMuUHJvY2Vzc0Vudj4ge1xuICBjb25zdCBob21lRGlyID0gb3B0aW9ucy5ob21lRGlyID8/IG9zLmhvbWVkaXIoKTtcbiAgY29uc3QgY29udGV4dCA9IGF3YWl0IGJpbi5lbnN1cmUoXCJmcnBjXCIsIGZycERvd25sb2FkVXJsLCB7XG4gICAgYXV0b1VucGFja2FnZTogdHJ1ZSxcbiAgICBob21lRGlyLFxuICAgIG1pblZlcnNpb246IEZSUF9WRVJTSU9OLFxuICAgIHNlbGVjdG9yOiAoeyBzb3VyY2UgfSkgPT4gc2VsZWN0RnJwYyhzb3VyY2UpLFxuICAgIHZlcnNpb25QYXJzZXI6ICh7IHN0ZG91dCwgc3RkZXJyIH0pID0+IHtcbiAgICAgIGNvbnN0IHZlcnNpb24gPSBiaW4ucGFyc2VWZXJzaW9uKHsgc3Rkb3V0LCBzdGRlcnIgfSk7XG4gICAgICByZXR1cm4gdmVyc2lvbiA9PT0gRlJQX1ZFUlNJT04gPyB2ZXJzaW9uIDogdW5kZWZpbmVkO1xuICAgIH0sXG4gIH0pO1xuICByZXR1cm4ge1xuICAgIC4uLnByb2Nlc3MuZW52LFxuICAgIEhPTUU6IGhvbWVEaXIsXG4gICAgUEFUSDogW2NvbnRleHQuYmluRGlyLCBwcm9jZXNzLmVudi5QQVRIID8/IFwiXCJdLmpvaW4oZGVsaW1pdGVyKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gZnJwQXJjaGl2ZURpcmVjdG9yeShcbiAgcGxhdGZvcm06IE5vZGVKUy5QbGF0Zm9ybSA9IHByb2Nlc3MucGxhdGZvcm0sXG4gIGFyY2g6IHN0cmluZyA9IHByb2Nlc3MuYXJjaCxcbik6IHN0cmluZyB7XG4gIHJldHVybiBmcnBBc3NldE5hbWUoRlJQX1ZFUlNJT04sIHBsYXRmb3JtLCBhcmNoKS5yZXBsYWNlKC9cXC50YXJcXC5neiQvLCBcIlwiKTtcbn1cblxuZnVuY3Rpb24gdG9tbFN0cmluZyh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbn1cblxuLyoqIFJlbmRlciBgfi8uZnJwYy9mcnBjLnRvbWxgIGZvciB0aGUgcmVzb2x2ZWQgdHVubmVsLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlRnJwQ29uZmlnKFxuICByZXNvbHZlZDogRnJwQ29uZmlnLFxuICBjaGlsZEVudjogTm9kZUpTLlByb2Nlc3NFbnYsXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBkaXJlY3RvcnkgPSBqb2luKGNoaWxkRW52LkhPTUUgPz8gb3MuaG9tZWRpcigpLCBcIi5mcnBjXCIpO1xuICBjb25zdCBwYXRoID0gam9pbihkaXJlY3RvcnksIFwiZnJwYy50b21sXCIpO1xuICBhd2FpdCBta2RpcihkaXJlY3RvcnksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICBjb25zdCBsaW5lcyA9IFtcbiAgICBgc2VydmVyQWRkciA9ICR7dG9tbFN0cmluZyhyZXNvbHZlZC5zZXJ2ZXIpfWAsXG4gICAgYHNlcnZlclBvcnQgPSAke3Jlc29sdmVkLnNlcnZlclBvcnR9YCxcbiAgICBgdHJhbnNwb3J0LnByb3RvY29sID0gJHt0b21sU3RyaW5nKHJlc29sdmVkLnByb3RvY29sKX1gLFxuICBdO1xuICBpZiAocmVzb2x2ZWQudG9rZW4pIGxpbmVzLnB1c2goYGF1dGgudG9rZW4gPSAke3RvbWxTdHJpbmcocmVzb2x2ZWQudG9rZW4pfWApO1xuICBsaW5lcy5wdXNoKFxuICAgIFwiXCIsXG4gICAgXCJbW3Byb3hpZXNdXVwiLFxuICAgIGBuYW1lID0gJHt0b21sU3RyaW5nKHJlc29sdmVkLnByb3h5TmFtZSl9YCxcbiAgICAndHlwZSA9IFwiaHR0cFwiJyxcbiAgICBgbG9jYWxQb3J0ID0gJHtyZXNvbHZlZC5wb3J0fWAsXG4gICAgYGN1c3RvbURvbWFpbnMgPSBbJHt0b21sU3RyaW5nKHJlc29sdmVkLnB1YmxpY0RvbWFpbil9XWAsXG4gICAgXCJcIixcbiAgKTtcbiAgYXdhaXQgd3JpdGVGaWxlKHBhdGgsIGxpbmVzLmpvaW4oXCJcXG5cIikpO1xuICByZXR1cm4gcGF0aDtcbn1cblxuLyoqIExhdW5jaCBmcnBjIGFzIGEgY2hpbGQgcHJvY2VzcyAoY2FsbGVyIHN1cGVydmlzZXMgYW5kIHRlcm1pbmF0ZXMgaXQpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0YXJ0RnJwKFxuICByZXNvbHZlZDogRnJwQ29uZmlnLFxuICBjaGlsZEVudjogTm9kZUpTLlByb2Nlc3NFbnYsXG4gIGNvbmZpZ1BhdGg6IHN0cmluZyxcbik6IFJldHVyblR5cGU8dHlwZW9mIHNwYXduPiB7XG4gIGxvZ2dlci5pbmZvKGBmcnBjIHR1bm5lbGluZyBodHRwczovLyR7cmVzb2x2ZWQucHVibGljRG9tYWlufSAtPiA6JHtyZXNvbHZlZC5wb3J0fWApO1xuICByZXR1cm4gc3Bhd24oXCJmcnBjXCIsIFtcIi1jXCIsIGNvbmZpZ1BhdGhdLCB7IGVudjogY2hpbGRFbnYsIHN0ZGlvOiBcImluaGVyaXRcIiB9KTtcbn1cbiJdfQ==
|
package/lib/src/gate.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export interface GateOptions {
|
|
|
40
40
|
* inert (everything passes through) - a tunnel with no public domain gates
|
|
41
41
|
* nothing.
|
|
42
42
|
*/
|
|
43
|
-
publicDomain?: string;
|
|
43
|
+
publicDomain?: string | readonly string[];
|
|
44
44
|
/**
|
|
45
45
|
* Extra `x-` request headers tunnel traffic may forward (unioned with the
|
|
46
46
|
* built-in allow-list). Every other `x-` header is stripped from tunnel traffic.
|
|
@@ -56,11 +56,11 @@ export interface GateOptions {
|
|
|
56
56
|
gatePaths?: readonly string[];
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
* True when the request's `Host` is the tunnel's public
|
|
60
|
-
* over
|
|
61
|
-
* domain is configured, nothing is tunnel traffic.
|
|
59
|
+
* True when the request's `Host` is one of the tunnel's public domains - i.e. it
|
|
60
|
+
* came in over Portr or FRP. Case-insensitive; the optional `:port` is ignored.
|
|
61
|
+
* When no public domain is configured, nothing is tunnel traffic.
|
|
62
62
|
*/
|
|
63
|
-
export declare function isTunnelHost(req: IncomingMessage, publicDomain: string | undefined): boolean;
|
|
63
|
+
export declare function isTunnelHost(req: IncomingMessage, publicDomain: string | readonly string[] | undefined): boolean;
|
|
64
64
|
/**
|
|
65
65
|
* Client IP for rate-limiting: the RIGHTMOST `x-forwarded-for` entry (the value
|
|
66
66
|
* the nearest trusted hop - portr - wrote), else the socket address. Reading the
|
package/lib/src/gate.js
CHANGED
|
@@ -26,15 +26,16 @@ import { toHeaderPolicy } from "./headers.js";
|
|
|
26
26
|
const logger = log.logger("tunnel:gate");
|
|
27
27
|
export const AUTH_PREFIX = "/api/email/auth";
|
|
28
28
|
/**
|
|
29
|
-
* True when the request's `Host` is the tunnel's public
|
|
30
|
-
* over
|
|
31
|
-
* domain is configured, nothing is tunnel traffic.
|
|
29
|
+
* True when the request's `Host` is one of the tunnel's public domains - i.e. it
|
|
30
|
+
* came in over Portr or FRP. Case-insensitive; the optional `:port` is ignored.
|
|
31
|
+
* When no public domain is configured, nothing is tunnel traffic.
|
|
32
32
|
*/
|
|
33
33
|
export function isTunnelHost(req, publicDomain) {
|
|
34
34
|
if (!publicDomain)
|
|
35
35
|
return false;
|
|
36
36
|
const host = (req.headers.host ?? "").toLowerCase().split(":")[0];
|
|
37
|
-
|
|
37
|
+
const domains = typeof publicDomain === "string" ? [publicDomain] : publicDomain;
|
|
38
|
+
return domains.some((domain) => host === domain.toLowerCase().split(":")[0]);
|
|
38
39
|
}
|
|
39
40
|
/**
|
|
40
41
|
* Client IP for rate-limiting: the RIGHTMOST `x-forwarded-for` entry (the value
|
|
@@ -254,4 +255,4 @@ export function mountGate(opts, _addRoute, addMiddleware) {
|
|
|
254
255
|
});
|
|
255
256
|
addMiddleware("/", gateMiddleware);
|
|
256
257
|
}
|
|
257
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBR0gsT0FBTyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVwRCxPQUFPLEVBQUUsY0FBYyxFQUFxQixNQUFNLGNBQWMsQ0FBQztBQUdqRSxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBT3pDLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxpQkFBaUIsQ0FBQztBQTRCN0M7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsR0FBb0IsRUFBRSxZQUFnQztJQUNqRixJQUFJLENBQUMsWUFBWTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ2hDLE1BQU0sSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLE9BQU8sSUFBSSxLQUFLLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDM0QsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBQyxHQUFvQjtJQUMzQyxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDakQsTUFBTSxLQUFLLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUMv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RyxFQUFFLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEUsQ0FBQyxDQUFtQixDQUFDO0lBQ3JCLGFBQWEsQ0FBQyxXQUFXLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFFeEMsNkVBQTZFO0lBRTdFLE1BQU0sY0FBYyxHQUFHLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUU7UUFDL0MsTUFBTSxNQUFNLEdBQUcsTUFBTSxXQUFXLENBQUMsR0FBRyxFQUFFLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUN2RixJQUFJLE1BQU0sS0FBSyxNQUFNO1lBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQzs7WUFDMUQsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDLENBQW1CLENBQUM7SUFFckIsYUFBYSxDQUFDLEdBQUcsRUFBRSxjQUFjLENBQUMsQ0FBQztBQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgdHVubmVsJ3MgaW4tYXBwIEFVVEggR0FURSAtIEV4cHJlc3MgbWlkZGxld2FyZSArIGxvZ2luIHJvdXRlcyB0aGVcbiAqIHtAbGluayBBdXRoR2F0ZVBsdWdpbn0gcmVnaXN0ZXJzIG9uIHRoZSBhcHAncyBPV04gc2VydmVyIHZpYSBgdGhpcy5jb250ZXh0YC5cbiAqXG4gKiBUaGUgZ2F0ZSBpcyBNSURETEVXQVJFLCBub3QgYSByZXZlcnNlIHByb3h5IC0gdGhlIGFwcCBpcyB0aGUgcHJvY2Vzcywgc28gdGhlcmUgaXNcbiAqIG5vdGhpbmcgdG8gZm9yd2FyZCB0by4gSXQgZWl0aGVyIHNob3J0LWNpcmN1aXRzICg0MDEsIG9yIGFuc3dlcnMgdGhlIG9wZW4gbG9naW5cbiAqIHJvdXRlcykgb3IgY2FsbHMgYG5leHQoKWAgdG8gbGV0IHRoZSBhcHAncyByZWFsIGhhbmRsZXJzIHJ1bi4gSXQgaXMgdGhlXG4gKiBcInN0YW5kcyBpbiBmb3IgQXBwS2l0IGF1dGhcIiBwYXRoOlxuICogYSBwb3J0ciBjYWxsZXIgYXV0aGVudGljYXRlcyB3aXRoIEJldHRlciBBdXRoIE9UUCBvciBhIHBhc3NrZXksIGFuZCBvblxuICogc3VjY2VzcyB0aGUgZ2F0ZSBpbmplY3RzIHRoZSBpZGVudGl0eSBoZWFkZXJzIEFwcEtpdCByZWFkcy5cbiAqXG4gKiBXSElDSCBUUkFGRklDIElTIEdBVEVEIC0gdGhlIGBIb3N0YCBoZWFkZXIsIG5vdCB0aGUgc29ja2V0LiBwb3J0cidzIGNsaWVudFxuICogZm9yd2FyZHMgd2l0aCBHbydzIGBodHRwdXRpbC5OZXdTaW5nbGVIb3N0UmV2ZXJzZVByb3h5YCBhbmQgYSBgRGlyZWN0b3JgIHRoYXRcbiAqIFBSRVNFUlZFUyB0aGUgb3JpZ2luYWwgYEhvc3RgLCBzbyB0dW5uZWwgcmVxdWVzdHMgYXJyaXZlIHdpdGhcbiAqIGBIb3N0OiA8c3ViZG9tYWluPi48c2VydmVyPmAgKHRoZSBwdWJsaWMgZG9tYWluKS4gQSBsb2NhbCBwcm9jZXNzIGhpdHRpbmcgdGhlXG4gKiBhcHAgZGlyZWN0bHkgc2VuZHMgYEhvc3Q6IDEyNy4wLjAuMTo8cG9ydD5gIC8gYGxvY2FsaG9zdGAuIFNvIE9OTFkgcmVxdWVzdHMgd2hvc2VcbiAqIGBIb3N0YCBtYXRjaGVzIHRoZSBjb25maWd1cmVkIHB1YmxpYyBkb21haW4gYXJlIGdhdGVkOyB0aGUgcGxhdGZvcm0gZnJvbnQgZG9vclxuICogYW5kIGFueSBvdGhlciBsb2NhbCBjbGllbnQgcGFzcyB0aHJvdWdoIHVudG91Y2hlZC4gVGhlcmUgaXMgbm8gcG9ydHItaW5qZWN0ZWRcbiAqIGlkZW50aWZ5aW5nIGhlYWRlciBhbmQgbm8gVENQL3NvdXJjZS1JUCBzaWduYWwgdG8gdXNlIGluc3RlYWQgKHRoZSBjbGllbnQgZGlhbHNcbiAqIHRoZSB0YXJnZXQgb3ZlciBwbGFpbiBsb29wYmFjaykuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB0eXBlIHsgSW5jb21pbmdNZXNzYWdlIH0gZnJvbSBcIm5vZGU6aHR0cFwiO1xuaW1wb3J0IHsgbG9nLCB0b2tlbiB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3RIYW5kbGVyLCBSZXNwb25zZSB9IGZyb20gXCJleHByZXNzXCI7XG5pbXBvcnQgeyB0b0hlYWRlclBvbGljeSwgdHlwZSBIZWFkZXJQb2xpY3kgfSBmcm9tIFwiLi9oZWFkZXJzLnRzXCI7XG5pbXBvcnQgdHlwZSB7IEF1dGhHYXRlQXBpIH0gZnJvbSBcIi4vcGx1Z2luLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJ0dW5uZWw6Z2F0ZVwiKTtcblxudHlwZSBXZWJSZXF1ZXN0SW5wdXQgPSBJbmNvbWluZ01lc3NhZ2UgJiB7XG4gIGJvZHk/OiB1bmtub3duO1xuICBvcmlnaW5hbFVybD86IHN0cmluZztcbn07XG5cbmV4cG9ydCBjb25zdCBBVVRIX1BSRUZJWCA9IFwiL2FwaS9lbWFpbC9hdXRoXCI7XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgbW91bnRHYXRlfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2F0ZU9wdGlvbnMge1xuICAvKiogVGhlIGluLXByb2Nlc3MgZ2F0ZSBBUEkgKHNlc3Npb24vcmVxdWVzdC92ZXJpZnkvc3RhdHVzKS4gKi9cbiAgZ2F0ZTogQXV0aEdhdGVBcGk7XG4gIC8qKlxuICAgKiBUaGUgcHVibGljIGA8c3ViZG9tYWluPi48c2VydmVyPmAgdGhhdCBpZGVudGlmaWVzIHBvcnRyIHRyYWZmaWMgYnkgYEhvc3RgLlxuICAgKiBXaGVuIGFic2VudCwgbm8gcmVxdWVzdCBpcyBldmVyIGNsYXNzaWZpZWQgYXMgdHVubmVsIHRyYWZmaWMgYW5kIHRoZSBnYXRlIGlzXG4gICAqIGluZXJ0IChldmVyeXRoaW5nIHBhc3NlcyB0aHJvdWdoKSAtIGEgdHVubmVsIHdpdGggbm8gcHVibGljIGRvbWFpbiBnYXRlc1xuICAgKiBub3RoaW5nLlxuICAgKi9cbiAgcHVibGljRG9tYWluPzogc3RyaW5nO1xuICAvKipcbiAgICogRXh0cmEgYHgtYCByZXF1ZXN0IGhlYWRlcnMgdHVubmVsIHRyYWZmaWMgbWF5IGZvcndhcmQgKHVuaW9uZWQgd2l0aCB0aGVcbiAgICogYnVpbHQtaW4gYWxsb3ctbGlzdCkuIEV2ZXJ5IG90aGVyIGB4LWAgaGVhZGVyIGlzIHN0cmlwcGVkIGZyb20gdHVubmVsIHRyYWZmaWMuXG4gICAqL1xuICBmb3J3YXJkSGVhZGVycz86IHJlYWRvbmx5IHN0cmluZ1tdO1xuICAvKipcbiAgICogUGF0aCBwcmVmaXhlcyB0aGF0IHJlcXVpcmUgYSB2YWxpZCBzZXNzaW9uLCBiZXlvbmQgdGhlIGJ1aWx0LWluIGAvYXBpL2AuXG4gICAqIFRoZSBkZWZhdWx0IGdhdGluZyBtb2RlbCBhc3N1bWVzIGEgc2VsZi1wcm90ZWN0aW5nIFNQQTogc3RhdGljIGxvYWRzIGZyZWVseVxuICAgKiBzbyB0aGUgYXBwIGNhbiByZW5kZXIsIGFuZCBvbmx5IGAvYXBpLypgIGlzIGdhdGVkLiBBbiBhcHAgd2hvc2UgcHJpdmlsZWdlZFxuICAgKiBzdXJmYWNlIGlzIE5PVCB1bmRlciBgL2FwaS9gIChlLmcuIGEgV2ViU29ja2V0IGF0IGAvd3NgKSBsaXN0cyB0aG9zZSBwcmVmaXhlc1xuICAgKiBoZXJlIHNvIHRoZXkgYXJlIGdhdGVkIHRvby4gTG9naW4gcm91dGVzIChgQVVUSF9QUkVGSVhgKSBhcmUgYWx3YXlzIG9wZW4uXG4gICAqL1xuICBnYXRlUGF0aHM/OiByZWFkb25seSBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBUcnVlIHdoZW4gdGhlIHJlcXVlc3QncyBgSG9zdGAgaXMgdGhlIHR1bm5lbCdzIHB1YmxpYyBkb21haW4gLSBpLmUuIGl0IGNhbWUgaW5cbiAqIG92ZXIgcG9ydHIuIENhc2UtaW5zZW5zaXRpdmU7IHRoZSBvcHRpb25hbCBgOnBvcnRgIGlzIGlnbm9yZWQuIFdoZW4gbm8gcHVibGljXG4gKiBkb21haW4gaXMgY29uZmlndXJlZCwgbm90aGluZyBpcyB0dW5uZWwgdHJhZmZpYy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVHVubmVsSG9zdChyZXE6IEluY29taW5nTWVzc2FnZSwgcHVibGljRG9tYWluOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgaWYgKCFwdWJsaWNEb21haW4pIHJldHVybiBmYWxzZTtcbiAgY29uc3QgaG9zdCA9IChyZXEuaGVhZGVycy5ob3N0ID8/IFwiXCIpLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCI6XCIpWzBdO1xuICByZXR1cm4gaG9zdCA9PT0gcHVibGljRG9tYWluLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCI6XCIpWzBdO1xufVxuXG4vKipcbiAqIENsaWVudCBJUCBmb3IgcmF0ZS1saW1pdGluZzogdGhlIFJJR0hUTU9TVCBgeC1mb3J3YXJkZWQtZm9yYCBlbnRyeSAodGhlIHZhbHVlXG4gKiB0aGUgbmVhcmVzdCB0cnVzdGVkIGhvcCAtIHBvcnRyIC0gd3JvdGUpLCBlbHNlIHRoZSBzb2NrZXQgYWRkcmVzcy4gUmVhZGluZyB0aGVcbiAqIHJpZ2h0bW9zdCwgbm90IHRoZSBsZWZ0bW9zdCwgc3RvcHMgYSBjYWxsZXIgbWludGluZyBhIGZyZXNoIHJhdGUtbGltaXQgYnVja2V0IGJ5XG4gKiB2YXJ5aW5nIHRoZSBoZWFkZXIuIENhbGxlZCBiZWZvcmUge0BsaW5rIHN0cmlwSGVhZGVyc30uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGllbnRJcChyZXE6IEluY29taW5nTWVzc2FnZSk6IHN0cmluZyB7XG4gIGNvbnN0IGZvcndhcmRlZCA9IHJlcS5oZWFkZXJzW1wieC1mb3J3YXJkZWQtZm9yXCJdO1xuICBjb25zdCBjaGFpbiA9IChBcnJheS5pc0FycmF5KGZvcndhcmRlZCkgPyBmb3J3YXJkZWQuam9pbihcIixcIikgOiAoZm9yd2FyZGVkID8/IFwiXCIpKVxuICAgIC5zcGxpdChcIixcIilcbiAgICAubWFwKChlbnRyeSkgPT4gZW50cnkudHJpbSgpKVxuICAgIC5maWx0ZXIoQm9vbGVhbik7XG4gIHJldHVybiBjaGFpbi5hdCgtMSkgPz8gcmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzID8/IFwidW5rbm93blwiO1xufVxuXG4vKipcbiAqIFJlbW92ZSB0aGUgZ2F0ZSdzIHNlc3Npb24gY29va2llIGZyb20gdGhlIGBDb29raWVgIGhlYWRlciBiZWZvcmUgdGhlIGFwcCdzXG4gKiBoYW5kbGVycyBydW4sIHNvIHRoZSBhcHAgbmV2ZXIgc2VlcyBgZGJ4X2F1dGhgIChpdCBpcyB0aGUgZ2F0ZSdzIGNvbmNlcm4pLlxuICogUHJlc2VydmVzIG90aGVyIGNvb2tpZXM7IGRlbGV0ZXMgdGhlIGhlYWRlciB3aGVuIGl0IGJlY29tZXMgZW1wdHkuXG4gKi9cbmZ1bmN0aW9uIHN0cmlwU2Vzc2lvbkNvb2tpZShyZXE6IEluY29taW5nTWVzc2FnZSk6IHZvaWQge1xuICBjb25zdCByYXcgPSByZXEuaGVhZGVycy5jb29raWU7XG4gIGlmICghcmF3KSByZXR1cm47XG4gIGNvbnN0IGtlcHQgPSByYXdcbiAgICAuc3BsaXQoXCI7XCIpXG4gICAgLm1hcCgoYykgPT4gYy50cmltKCkpXG4gICAgLmZpbHRlcigoYykgPT4gYyAmJiAhYy5zdGFydHNXaXRoKFwiZGJ4LXRvb2xzLWF1dGg9XCIpICYmICFjLnN0YXJ0c1dpdGgoXCJkYngtdG9vbHMtcGFzc2tleT1cIikpO1xuICBpZiAoa2VwdC5sZW5ndGgpIHJlcS5oZWFkZXJzLmNvb2tpZSA9IGtlcHQuam9pbihcIjsgXCIpO1xuICBlbHNlIGRlbGV0ZSByZXEuaGVhZGVycy5jb29raWU7XG59XG5cbi8qKlxuICogUHJlc2VudCBhIHBhc3N3b3JkbGVzcy1hdXRoZW50aWNhdGVkIGNhbGxlciB0byB0aGUgYXBwIHRoZSBTQU1FIHdheSBhIHBsYXRmb3JtIGZyb250XG4gKiBkb29yIGRvZXM6IHNldCB0aGUgZnJvbnQtZG9vciBpZGVudGl0eSBoZWFkZXJzIHRvIHRoZSB2ZXJpZmllZCBhZGRyZXNzIChBcHBLaXRcbiAqIHJlYWRzIHtAbGluayB0b2tlbi5VU0VSX0lEX0hFQURFUn0gZm9yIHRoZSBPQk8gdXNlciBpZCksIHNvIHRoZSBhcHAgbmVlZHMgbm9cbiAqIGdhdGUtc3BlY2lmaWMgY29kZSBwYXRoLlxuICpcbiAqIFdoYXQgdGhlIGdhdGUgQ0FOTk9UIHNldCBpcyB7QGxpbmsgdG9rZW4uQUNDRVNTX1RPS0VOX0hFQURFUn06IGFuIGF1dGggc2Vzc2lvblxuICogcHJvdmVzIGFuIGVtYWlsLCBub3QgcG9zc2Vzc2lvbiBvZiBhIERhdGFicmlja3MgY3JlZGVudGlhbC4gSXRzIGFic2VuY2UgaXMgd2hhdFxuICogYEBkYngtdG9vbHMvYXBwa2l0YCdzIGBpZGVudGl0eTogXCJhdXRvXCJgIGRldGVjdHMsIHNvIGEgZ2F0ZWQgcmVxdWVzdCBydW5zIGFzIHRoZVxuICogYXBwIHNlcnZpY2UgcHJpbmNpcGFsIGluc3RlYWQgb2YgdGhyb3dpbmcuXG4gKi9cbmZ1bmN0aW9uIGluamVjdElkZW50aXR5KHJlcTogSW5jb21pbmdNZXNzYWdlLCBlbWFpbDogc3RyaW5nKTogdm9pZCB7XG4gIHJlcS5oZWFkZXJzW3Rva2VuLlVTRVJfSURfSEVBREVSXSA9IGVtYWlsO1xuICByZXEuaGVhZGVyc1t0b2tlbi5VU0VSX0VNQUlMX0hFQURFUl0gPSBlbWFpbDtcbn1cblxuLyoqIFJlYWQgdGhlIHJhdyByZXF1ZXN0IGJvZHkgYXMgdGV4dCAoQXBwS2l0IHBhcnNlcyBKU09OLCBidXQgdGhlIGdhdGUgcm91dGVzXG4gKiBhcmUgbW91bnRlZCBiZWZvcmUgdGhhdCBydW5zIGZvciB0dW5uZWwgdHJhZmZpYywgc28gcmVhZCBkZWZlbnNpdmVseSkuICovXG5mdW5jdGlvbiByZWFkQm9keShyZXE6IFdlYlJlcXVlc3RJbnB1dCk6IFByb21pc2U8c3RyaW5nPiB7XG4gIC8vIEFwcEtpdCdzIGpzb24gYm9keS1wYXJzZXIgbWF5IGhhdmUgYWxyZWFkeSBwb3B1bGF0ZWQgcmVxLmJvZHk7IHByZWZlciBpdC5cbiAgaWYgKHJlcS5ib2R5ICE9PSB1bmRlZmluZWQgJiYgcmVxLmJvZHkgIT09IG51bGwpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHR5cGVvZiByZXEuYm9keSA9PT0gXCJzdHJpbmdcIiA/IHJlcS5ib2R5IDogSlNPTi5zdHJpbmdpZnkocmVxLmJvZHkpKTtcbiAgfVxuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBsZXQgZGF0YSA9IFwiXCI7XG4gICAgcmVxLm9uKFwiZGF0YVwiLCAoY2h1bmspID0+IChkYXRhICs9IGNodW5rKSk7XG4gICAgcmVxLm9uKFwiZW5kXCIsICgpID0+IHJlc29sdmUoZGF0YSkpO1xuICAgIHJlcS5vbihcImVycm9yXCIsICgpID0+IHJlc29sdmUoZGF0YSkpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdlYkhlYWRlcnMocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiBIZWFkZXJzIHtcbiAgY29uc3QgaGVhZGVycyA9IG5ldyBIZWFkZXJzKCk7XG4gIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhyZXEuaGVhZGVycykpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgIGZvciAoY29uc3QgaXRlbSBvZiB2YWx1ZSkgaGVhZGVycy5hcHBlbmQobmFtZSwgaXRlbSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBoZWFkZXJzLnNldChuYW1lLCB2YWx1ZSk7XG4gICAgfVxuICB9XG4gIGhlYWRlcnMuc2V0KFwieC1yZWFsLWlwXCIsIGNsaWVudElwKHJlcSkpO1xuICByZXR1cm4gaGVhZGVycztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdlYlJlcXVlc3QocmVxOiBXZWJSZXF1ZXN0SW5wdXQpOiBQcm9taXNlPGdsb2JhbFRoaXMuUmVxdWVzdD4ge1xuICBjb25zdCBob3N0ID0gcmVxLmhlYWRlcnMuaG9zdCA/PyBcImxvY2FsaG9zdFwiO1xuICBjb25zdCBob3N0bmFtZSA9IGhvc3Quc3BsaXQoXCI6XCIpWzBdPy50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBwcm90b2NvbCA9IGhvc3RuYW1lID09PSBcImxvY2FsaG9zdFwiIHx8IGhvc3RuYW1lID09PSBcIjEyNy4wLjAuMVwiID8gXCJodHRwXCIgOiBcImh0dHBzXCI7XG4gIGNvbnN0IG1ldGhvZCA9IChyZXEubWV0aG9kID8/IFwiR0VUXCIpLnRvVXBwZXJDYXNlKCk7XG4gIGNvbnN0IGJvZHkgPSBtZXRob2QgPT09IFwiR0VUXCIgfHwgbWV0aG9kID09PSBcIkhFQURcIiA/IHVuZGVmaW5lZCA6IGF3YWl0IHJlYWRCb2R5KHJlcSk7XG4gIHJldHVybiBuZXcgZ2xvYmFsVGhpcy5SZXF1ZXN0KGAke3Byb3RvY29sfTovLyR7aG9zdH0ke3JlcS5vcmlnaW5hbFVybCB8fCByZXEudXJsfWAsIHtcbiAgICBtZXRob2QsXG4gICAgaGVhZGVyczogd2ViSGVhZGVycyhyZXEpLFxuICAgIC4uLihib2R5ID8geyBib2R5IH0gOiB7fSksXG4gIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VuZFdlYlJlc3BvbnNlKHJlczogUmVzcG9uc2UsIHJlc3BvbnNlOiBnbG9iYWxUaGlzLlJlc3BvbnNlKTogUHJvbWlzZTx2b2lkPiB7XG4gIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiByZXNwb25zZS5oZWFkZXJzLmVudHJpZXMoKSkge1xuICAgIGlmIChuYW1lLnRvTG93ZXJDYXNlKCkgIT09IFwic2V0LWNvb2tpZVwiKSByZXMuc2V0SGVhZGVyKG5hbWUsIHZhbHVlKTtcbiAgfVxuICBjb25zdCBjb29raWVzID0gcmVzcG9uc2UuaGVhZGVycy5nZXRTZXRDb29raWUoKTtcbiAgaWYgKGNvb2tpZXMubGVuZ3RoKSByZXMuc2V0SGVhZGVyKFwic2V0LWNvb2tpZVwiLCBjb29raWVzKTtcbiAgY29uc3QgYm9keSA9IEJ1ZmZlci5mcm9tKGF3YWl0IHJlc3BvbnNlLmFycmF5QnVmZmVyKCkpO1xuICByZXMuc3RhdHVzKHJlc3BvbnNlLnN0YXR1cykuc2VuZChib2R5KTtcbn1cblxuLyoqXG4gKiBXaGF0IHRoZSBjYWxsZXIgc2hvdWxkIGRvIHdpdGggYSByZXF1ZXN0LCBmcm9tIHtAbGluayBnYXRlUmVxdWVzdH0uXG4gKlxuICogICAtIGBwYXNzYCAtIG5vdCB0dW5uZWwgdHJhZmZpYywgb3IgYW4gb3BlbiBsb2dpbiByb3V0ZS4gRm9yd2FyZCB1bnRvdWNoZWQuXG4gKiAgIC0gYGFsbG93YCAtIHR1bm5lbCB0cmFmZmljIHRoYXQgaXMgYXV0aG9yaXplZC4gVGhlIHJlcXVlc3QncyBoZWFkZXJzIGhhdmVcbiAqICAgICBBTFJFQURZIGJlZW4gcmV3cml0dGVuIChwb2xpY3kgYXBwbGllZCwgaWRlbnRpdHkgaW5qZWN0ZWQsIHNlc3Npb24gY29va2llXG4gKiAgICAgc3RyaXBwZWQpLCBzbyBmb3J3YXJkIGl0IGFzIGl0IG5vdyBzdGFuZHMuXG4gKiAgIC0gYGRlbnlgIC0gdHVubmVsIHRyYWZmaWMgd2l0aCBubyB2YWxpZCBzZXNzaW9uLiBBbnN3ZXIgYDQwMWAgd2l0aFxuICogICAgIHtAbGluayBBVVRIX1BSRUZJWH0gYXMgdGhlIGxvZ2luIHBhdGguXG4gKi9cbmV4cG9ydCB0eXBlIEdhdGVBY3Rpb24gPSBcInBhc3NcIiB8IFwiYWxsb3dcIiB8IFwiZGVueVwiO1xuXG4vKipcbiAqIFRIRSBnYXRpbmcgZGVjaXNpb24sIGZvciBvbmUgcmVxdWVzdCwgaW5kZXBlbmRlbnQgb2YgaG93IGl0IHdpbGwgYmUgYW5zd2VyZWQuXG4gKlxuICogQm90aCBwYXRocyBjYWxsIHRoaXM6IHRoZSBFeHByZXNzIG1pZGRsZXdhcmUgYmVsb3cgKHdoZXJlIHRoZSBhcHAgaXMgdGhlXG4gKiBwcm9jZXNzKSBhbmQgYEBkYngtdG9vbHMvY2xpLXR1bm5lbGAncyByZXZlcnNlIHByb3h5ICh3aGVyZSB0aGUgYXBwIGlzIGEgY2hpbGRcbiAqIHByb2Nlc3Mgb24gYSBwcml2YXRlIHBvcnQpLiBBIGRpdmVyZ2VuY2UgYmV0d2VlbiB0aGVtIHdvdWxkIGJlIGEgc2VjdXJpdHkgYnVnXG4gKiB0aGUgc2Vjb25kIHBhdGggY291bGQgbm90IGJlIHRlc3RlZCBpbnRvIGFncmVlbWVudCAtIG9uZSBwYXRoIGZvcmdldHRpbmcgdG9cbiAqIHN0cmlwIGB4LWZvcndhcmRlZC1hY2Nlc3MtdG9rZW5gIGlzIGVub3VnaCAtIHNvIHRoZSBkZWNpc2lvbiwgdGhlIGhlYWRlclxuICogcmV3cml0aW5nLCBhbmQgdGhlIGlkZW50aXR5IGluamVjdGlvbiBsaXZlIGhlcmUgb25jZSBhbmQgdGhlIHRyYW5zcG9ydHMgb25seVxuICogZGlmZmVyIGluIGhvdyB0aGV5IFdSSVRFIHRoZSBvdXRjb21lLlxuICpcbiAqIE11dGF0ZXMgYHJlcS5oZWFkZXJzYCBvbiB0aGUgYGFsbG93YC9gcGFzc2Atd2l0aC1jb29raWUgcGF0aHMsIHdoaWNoIGlzIGV4YWN0bHlcbiAqIHdoYXQgYm90aCBjYWxsZXJzIHdhbnQ6IEV4cHJlc3MgaGFuZHMgdGhlIHNhbWUgb2JqZWN0IHRvIHRoZSBhcHAncyBoYW5kbGVycywgYW5kXG4gKiB0aGUgcHJveHkgZm9yd2FyZHMgaXQgdXBzdHJlYW0uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnYXRlUmVxdWVzdChcbiAgcmVxOiBJbmNvbWluZ01lc3NhZ2UsXG4gIG9wdGlvbnM6IEdhdGVPcHRpb25zICYgeyBoZWFkZXJQb2xpY3k/OiBIZWFkZXJQb2xpY3kgfSxcbik6IFByb21pc2U8R2F0ZUFjdGlvbj4ge1xuICBjb25zdCB7IGdhdGUsIHB1YmxpY0RvbWFpbiB9ID0gb3B0aW9ucztcbiAgLy8gTm90IHR1bm5lbCB0cmFmZmljIChwbGF0Zm9ybSBmcm9udCBkb29yLCBvciBhbnkgb3RoZXIgbG9jYWwgY2FsbGVyKTogdGhlXG4gIC8vIHJlcXVlc3QgaXMgYWxyZWFkeSBhdXRoZW50aWNhdGVkLCBvciBpcyBub3Qgb3VycyB0byBnYXRlLlxuICBpZiAoIWlzVHVubmVsSG9zdChyZXEsIHB1YmxpY0RvbWFpbikpIHJldHVybiBcInBhc3NcIjtcblxuICBjb25zdCBwYXRoID0gKHJlcS51cmwgPz8gXCIvXCIpLnNwbGl0KFwiP1wiKVswXSA/PyBcIi9cIjtcbiAgLy8gVGhlIGxvZ2luIGZsb3cgaXMgb3BlbiBzbyB0aGUgYnJvd3NlciBjYW4gcmVuZGVyIDxBdXRoR2F0ZT4gYW5kIHNpZ24gaW4uXG4gIGlmIChwYXRoLnN0YXJ0c1dpdGgoQVVUSF9QUkVGSVgpKSByZXR1cm4gXCJwYXNzXCI7XG5cbiAgLy8gQW50aS1zcG9vZjogb25seSB0aGUgZ2F0ZSBtYXkgYXNzZXJ0IGlkZW50aXR5IG9uIHR1bm5lbCB0cmFmZmljLlxuICBjb25zdCBwb2xpY3kgPSBvcHRpb25zLmhlYWRlclBvbGljeSA/PyB0b0hlYWRlclBvbGljeShvcHRpb25zLmZvcndhcmRIZWFkZXJzKTtcbiAgY29uc3QgcmVtb3ZlZCA9IHBvbGljeS5hcHBseShyZXEuaGVhZGVycyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik7XG4gIGlmIChyZW1vdmVkLmxlbmd0aCkgbG9nZ2VyLmRlYnVnKFwic3RyaXBwZWQgaW5ib3VuZCBoZWFkZXJzXCIsIHsgcmVtb3ZlZCB9KTtcblxuICBjb25zdCBnYXRlUGF0aHMgPSBvcHRpb25zLmdhdGVQYXRocyA/PyBbXTtcbiAgLy8gQSBwYXRoIGlzIGdhdGVkIGlmIGl0IGlzIHVuZGVyIGAvYXBpL2Agb3IgYW55IGNhbGxlci1zdXBwbGllZCBwcmVmaXggKGUuZy5cbiAgLy8gYC93c2AgZm9yIGEgV2ViU29ja2V0IGFwcCkuXG4gIGNvbnN0IGdhdGVkID1cbiAgICBwYXRoLnN0YXJ0c1dpdGgoXCIvYXBpL1wiKSB8fFxuICAgIGdhdGVQYXRocy5zb21lKChwcmVmaXgpID0+IHBhdGggPT09IHByZWZpeCB8fCBwYXRoLnN0YXJ0c1dpdGgoYCR7cHJlZml4fS9gKSk7XG5cbiAgLy8gQXBwLWdhdGluZyBtb2RlOiB3aGVuIGBnYXRlUGF0aHNgIGlzIHNldCB0aGUgY2FsbGVyIGlzIGZyb250aW5nIGEgd2hvbGUgYXBwXG4gIC8vIChub3QgYSBzZWxmLXByb3RlY3RpbmcgU1BBKSwgc28gYW4gdW5hdXRoZW50aWNhdGVkIHRvcC1sZXZlbCBicm93c2VyXG4gIC8vIG5hdmlnYXRpb24gaXMgZGVuaWVkIHRvbyDigJQgdGhlIHRyYW5zcG9ydCBhbnN3ZXJzIGl0IHdpdGggdGhlIGhvc3RlZCBsb2dpblxuICAvLyBwYWdlLCBwdXR0aW5nIHNpZ24taW4gaW4gZnJvbnQgb2YgdGhlIGFwcCBpbnN0ZWFkIG9mIGxvYWRpbmcgaXRzIHNoZWxsIHdpdGhcbiAgLy8gYSBkZWFkIGdhdGVkIHJlcXVlc3QuIE5vbi1uYXZpZ2F0aW9uIHN0YXRpYyAoYXNzZXRzKSBzdGlsbCBsb2FkcyBmcmVlbHkgc29cbiAgLy8gdGhlIGxvZ2luIHBhZ2UgYW5kIGFwcCBjYW4gcmVuZGVyLlxuICBjb25zdCBhcHBHYXRpbmcgPSBnYXRlUGF0aHMubGVuZ3RoID4gMDtcbiAgY29uc3QgbXVzdEF1dGggPSBnYXRlZCB8fCAoYXBwR2F0aW5nICYmIHdhbnRzTG9naW5QYWdlKHJlcSkpO1xuICBpZiAoIW11c3RBdXRoKSB7XG4gICAgc3RyaXBTZXNzaW9uQ29va2llKHJlcSk7XG4gICAgcmV0dXJuIFwicGFzc1wiO1xuICB9XG5cbiAgLy8gQSBnYXRlZCByZXF1ZXN0IG5lZWRzIGEgdmFsaWQgQmV0dGVyIEF1dGggc2Vzc2lvbi5cbiAgY29uc3QgZW1haWwgPSBhd2FpdCBnYXRlLnNlc3Npb24od2ViSGVhZGVycyhyZXEpKTtcbiAgaWYgKCFlbWFpbCkgcmV0dXJuIFwiZGVueVwiO1xuICBpbmplY3RJZGVudGl0eShyZXEsIGVtYWlsKTtcbiAgc3RyaXBTZXNzaW9uQ29va2llKHJlcSk7XG4gIHJldHVybiBcImFsbG93XCI7XG59XG5cbi8qKiBUaGUgYm9keSBvZiBhIGBkZW55YCwgc2hhcmVkIHNvIGJvdGggcGF0aHMgYW5zd2VyIGEgNDAxIGlkZW50aWNhbGx5LiAqL1xuZXhwb3J0IGNvbnN0IFVOQVVUSE9SSVpFRF9CT0RZID0ge1xuICBlcnJvcjogXCJhdXRoZW50aWNhdGlvbiByZXF1aXJlZFwiLFxuICBsb2dpblBhdGg6IEFVVEhfUFJFRklYLFxufSBhcyBjb25zdDtcblxuLyoqXG4gKiBXaGV0aGVyIGEgZGVuaWVkIHJlcXVlc3QgaXMgYSB0b3AtbGV2ZWwgQlJPV1NFUiBOQVZJR0FUSU9OIHRoYXQgc2hvdWxkIGJlXG4gKiBhbnN3ZXJlZCB3aXRoIHRoZSBob3N0ZWQgbG9naW4gcGFnZSByYXRoZXIgdGhhbiBhIDQwMS5cbiAqXG4gKiBBbiBhcHAgZnJvbnRlZCBieSB0aGUgZ2F0ZSAodmlhIGBnYXRlUGF0aHNgKSBtYXkgc2VydmUgaXRzIG93biBIVE1MIGZyb20gYW5cbiAqIHVuZ2F0ZWQgcGF0aCB3aGlsZSBpdHMgcHJpdmlsZWdlZCBzdXJmYWNlIChgL3dzYCwgYC9hcGlgKSBpcyBnYXRlZC4gQSBicm93c2VyXG4gKiBuYXZpZ2F0aW5nIHRvIGl0IHdvdWxkIG90aGVyd2lzZSBsb2FkIHRoZSBhcHAgc2hlbGwgYW5kIG9ubHkgc2VlIHRoZSBnYXRlZFxuICogcmVxdWVzdCBmYWlsLCB3aXRoIG5vIHdheSB0byBzaWduIGluLiBTZXJ2aW5nIHRoZSBsb2dpbiBwYWdlIG9uIHRoZSBuYXZpZ2F0aW9uXG4gKiBpdHNlbGYgcHV0cyBzaWduLWluIGluIGZyb250IG9mIHRoZSBhcHAuIEFwcGxpZXMgb25seSB0byBHRVQgcmVxdWVzdHMgdGhhdFxuICogYWNjZXB0IEhUTUwgYW5kIGFyZSBub3QgYXNraW5nIGZvciB0aGUgbG9naW4gQVBJIG9yIGFuIGFzc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gd2FudHNMb2dpblBhZ2UocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiBib29sZWFuIHtcbiAgY29uc3QgbWV0aG9kID0gKHJlcS5tZXRob2QgPz8gXCJHRVRcIikudG9VcHBlckNhc2UoKTtcbiAgaWYgKG1ldGhvZCAhPT0gXCJHRVRcIiAmJiBtZXRob2QgIT09IFwiSEVBRFwiKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IHBhdGggPSAocmVxLnVybCA/PyBcIi9cIikuc3BsaXQoXCI/XCIpWzBdID8/IFwiL1wiO1xuICBpZiAocGF0aC5zdGFydHNXaXRoKEFVVEhfUFJFRklYKSkgcmV0dXJuIGZhbHNlO1xuICBjb25zdCBhY2NlcHQgPSBTdHJpbmcocmVxLmhlYWRlcnMuYWNjZXB0ID8/IFwiXCIpO1xuICByZXR1cm4gYWNjZXB0LmluY2x1ZGVzKFwidGV4dC9odG1sXCIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVyIHRoZSBsb2dpbiByb3V0ZXMgYW5kIHRoZSBnYXRpbmcgbWlkZGxld2FyZSBvbiB0aGUgYXBwJ3MgRXhwcmVzc1xuICogaW5zdGFuY2UuIENhbGxlZCBmcm9tIHtAbGluayBBdXRoR2F0ZVBsdWdpbn0gd2l0aCB0aGUgcm91dGVyIEFwcEtpdCBoYW5kc1xuICogYGluamVjdFJvdXRlc2AsIHBsdXMgYHRoaXMuY29udGV4dC5hZGRNaWRkbGV3YXJlYCBmb3IgdGhlIGdsb2JhbCBnYXRlLlxuICpcbiAqIGBhZGRSb3V0ZWAvYGFkZE1pZGRsZXdhcmVgIGFyZSB1c2VkICh2aWEgdGhlIHBhc3NlZCBjYWxsYmFja3MpIGJlY2F1c2UgdGhlIGxvZ2luXG4gKiByb3V0ZXMgbGl2ZSBhdCBhbiBBQlNPTFVURSBwYXRoIChgL2FwaS9lbWFpbC9hdXRoLypgLCB0aGUgY2xpZW50J3MgY29udHJhY3QpLFxuICogbm90IHVuZGVyIHRoZSBwbHVnaW4ncyBgL2FwaS9hdXRoR2F0ZWAgYmFzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vdW50R2F0ZShcbiAgb3B0czogR2F0ZU9wdGlvbnMsXG4gIF9hZGRSb3V0ZTogKG1ldGhvZDogXCJnZXRcIiB8IFwicG9zdFwiLCBwYXRoOiBzdHJpbmcsIGhhbmRsZXI6IFJlcXVlc3RIYW5kbGVyKSA9PiB2b2lkLFxuICBhZGRNaWRkbGV3YXJlOiAocGF0aDogc3RyaW5nLCBoYW5kbGVyOiBSZXF1ZXN0SGFuZGxlcikgPT4gdm9pZCxcbik6IHZvaWQge1xuICBjb25zdCB7IGdhdGUsIHB1YmxpY0RvbWFpbiwgZm9yd2FyZEhlYWRlcnMsIGdhdGVQYXRocyB9ID0gb3B0cztcbiAgY29uc3QgaGVhZGVyUG9saWN5ID0gdG9IZWFkZXJQb2xpY3koZm9yd2FyZEhlYWRlcnMpO1xuICBsb2dnZXIuZGVidWcoXCJnYXRlIG1vdW50ZWRcIiwgeyBwdWJsaWNEb21haW4sIGZvcndhcmQ6IGhlYWRlclBvbGljeS5wYXR0ZXJucywgZ2F0ZVBhdGhzIH0pO1xuXG4gIC8vIEJldHRlciBBdXRoIGFuZCB0aGUgY29tcGF0aWJpbGl0eSByb3V0ZXMgc2hhcmUgb25lIGZldGNoLWNvbXBhdGlibGVcbiAgLy8gaGFuZGxlciBpbiBib3RoIGhvc3RpbmcgbW9kZXMuXG4gIGNvbnN0IGF1dGhIYW5kbGVyID0gKGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgIGlmICghaXNUdW5uZWxIb3N0KHJlcSwgcHVibGljRG9tYWluKSkge1xuICAgICAgY29uc3QgcGF0aCA9IChyZXEudXJsID8/IFwiL1wiKS5zcGxpdChcIj9cIilbMF0gPz8gXCIvXCI7XG4gICAgICBpZiAocGF0aC5lbmRzV2l0aChcIi9zdGF0dXNcIikpIHtcbiAgICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oeyBhdXRoZW50aWNhdGVkOiBmYWxzZSwgZW5hYmxlZDogZmFsc2UsIHBhc3NrZXlzRW5hYmxlZDogZmFsc2UgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXMuc3RhdHVzKDQwNCkuanNvbih7IGVycm9yOiBcIm5vdCBmb3VuZFwiIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCBzZW5kV2ViUmVzcG9uc2UocmVzLCBhd2FpdCBnYXRlLmhhbmRsZXIoYXdhaXQgd2ViUmVxdWVzdChyZXEpKSk7XG4gIH0pIGFzIFJlcXVlc3RIYW5kbGVyO1xuICBhZGRNaWRkbGV3YXJlKEFVVEhfUFJFRklYLCBhdXRoSGFuZGxlcik7XG5cbiAgLy8gLS0tIFRoZSBnYXRlIG1pZGRsZXdhcmUgKHJ1bnMgYmVmb3JlIHN0YXRpYyArIHRoZSBhcHAncyAvYXBpIGhhbmRsZXJzKSAtLS1cblxuICBjb25zdCBnYXRlTWlkZGxld2FyZSA9IChhc3luYyAocmVxLCByZXMsIG5leHQpID0+IHtcbiAgICBjb25zdCBhY3Rpb24gPSBhd2FpdCBnYXRlUmVxdWVzdChyZXEsIHsgZ2F0ZSwgcHVibGljRG9tYWluLCBoZWFkZXJQb2xpY3ksIGdhdGVQYXRocyB9KTtcbiAgICBpZiAoYWN0aW9uID09PSBcImRlbnlcIikgcmVzLnN0YXR1cyg0MDEpLmpzb24oVU5BVVRIT1JJWkVEX0JPRFkpO1xuICAgIGVsc2UgbmV4dCgpO1xuICB9KSBhcyBSZXF1ZXN0SGFuZGxlcjtcblxuICBhZGRNaWRkbGV3YXJlKFwiL1wiLCBnYXRlTWlkZGxld2FyZSk7XG59XG4iXX0=
|
|
258
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBR0gsT0FBTyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVwRCxPQUFPLEVBQUUsY0FBYyxFQUFxQixNQUFNLGNBQWMsQ0FBQztBQUdqRSxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBT3pDLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxpQkFBaUIsQ0FBQztBQTRCN0M7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQzFCLEdBQW9CLEVBQ3BCLFlBQW9EO0lBRXBELElBQUksQ0FBQyxZQUFZO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDaEMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEUsTUFBTSxPQUFPLEdBQUcsT0FBTyxZQUFZLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUM7SUFDakYsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQy9FLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxRQUFRLENBQUMsR0FBb0I7SUFDM0MsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lB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QU0sQ0FBQztnQkFDTixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQy9DLENBQUM7WUFDRCxPQUFPO1FBQ1QsQ0FBQztRQUNELE1BQU0sZUFBZSxDQUFDLEdBQUcsRUFBRSxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLENBQUMsQ0FBbUIsQ0FBQztJQUNyQixhQUFhLENBQUMsV0FBVyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBRXhDLDZFQUE2RTtJQUU3RSxNQUFNLGNBQWMsR0FBRyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFO1FBQy9DLE1BQU0sTUFBTSxHQUFHLE1BQU0sV0FBVyxDQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7UUFDdkYsSUFBSSxNQUFNLEtBQUssTUFBTTtZQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7O1lBQzFELElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQyxDQUFtQixDQUFDO0lBRXJCLGFBQWEsQ0FBQyxHQUFHLEVBQUUsY0FBYyxDQUFDLENBQUM7QUFDckMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhlIHR1bm5lbCdzIGluLWFwcCBBVVRIIEdBVEUgLSBFeHByZXNzIG1pZGRsZXdhcmUgKyBsb2dpbiByb3V0ZXMgdGhlXG4gKiB7QGxpbmsgQXV0aEdhdGVQbHVnaW59IHJlZ2lzdGVycyBvbiB0aGUgYXBwJ3MgT1dOIHNlcnZlciB2aWEgYHRoaXMuY29udGV4dGAuXG4gKlxuICogVGhlIGdhdGUgaXMgTUlERExFV0FSRSwgbm90IGEgcmV2ZXJzZSBwcm94eSAtIHRoZSBhcHAgaXMgdGhlIHByb2Nlc3MsIHNvIHRoZXJlIGlzXG4gKiBub3RoaW5nIHRvIGZvcndhcmQgdG8uIEl0IGVpdGhlciBzaG9ydC1jaXJjdWl0cyAoNDAxLCBvciBhbnN3ZXJzIHRoZSBvcGVuIGxvZ2luXG4gKiByb3V0ZXMpIG9yIGNhbGxzIGBuZXh0KClgIHRvIGxldCB0aGUgYXBwJ3MgcmVhbCBoYW5kbGVycyBydW4uIEl0IGlzIHRoZVxuICogXCJzdGFuZHMgaW4gZm9yIEFwcEtpdCBhdXRoXCIgcGF0aDpcbiAqIGEgcG9ydHIgY2FsbGVyIGF1dGhlbnRpY2F0ZXMgd2l0aCBCZXR0ZXIgQXV0aCBPVFAgb3IgYSBwYXNza2V5LCBhbmQgb25cbiAqIHN1Y2Nlc3MgdGhlIGdhdGUgaW5qZWN0cyB0aGUgaWRlbnRpdHkgaGVhZGVycyBBcHBLaXQgcmVhZHMuXG4gKlxuICogV0hJQ0ggVFJBRkZJQyBJUyBHQVRFRCAtIHRoZSBgSG9zdGAgaGVhZGVyLCBub3QgdGhlIHNvY2tldC4gcG9ydHIncyBjbGllbnRcbiAqIGZvcndhcmRzIHdpdGggR28ncyBgaHR0cHV0aWwuTmV3U2luZ2xlSG9zdFJldmVyc2VQcm94eWAgYW5kIGEgYERpcmVjdG9yYCB0aGF0XG4gKiBQUkVTRVJWRVMgdGhlIG9yaWdpbmFsIGBIb3N0YCwgc28gdHVubmVsIHJlcXVlc3RzIGFycml2ZSB3aXRoXG4gKiBgSG9zdDogPHN1YmRvbWFpbj4uPHNlcnZlcj5gICh0aGUgcHVibGljIGRvbWFpbikuIEEgbG9jYWwgcHJvY2VzcyBoaXR0aW5nIHRoZVxuICogYXBwIGRpcmVjdGx5IHNlbmRzIGBIb3N0OiAxMjcuMC4wLjE6PHBvcnQ+YCAvIGBsb2NhbGhvc3RgLiBTbyBPTkxZIHJlcXVlc3RzIHdob3NlXG4gKiBgSG9zdGAgbWF0Y2hlcyB0aGUgY29uZmlndXJlZCBwdWJsaWMgZG9tYWluIGFyZSBnYXRlZDsgdGhlIHBsYXRmb3JtIGZyb250IGRvb3JcbiAqIGFuZCBhbnkgb3RoZXIgbG9jYWwgY2xpZW50IHBhc3MgdGhyb3VnaCB1bnRvdWNoZWQuIFRoZXJlIGlzIG5vIHBvcnRyLWluamVjdGVkXG4gKiBpZGVudGlmeWluZyBoZWFkZXIgYW5kIG5vIFRDUC9zb3VyY2UtSVAgc2lnbmFsIHRvIHVzZSBpbnN0ZWFkICh0aGUgY2xpZW50IGRpYWxzXG4gKiB0aGUgdGFyZ2V0IG92ZXIgcGxhaW4gbG9vcGJhY2spLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEluY29taW5nTWVzc2FnZSB9IGZyb20gXCJub2RlOmh0dHBcIjtcbmltcG9ydCB7IGxvZywgdG9rZW4gfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0SGFuZGxlciwgUmVzcG9uc2UgfSBmcm9tIFwiZXhwcmVzc1wiO1xuaW1wb3J0IHsgdG9IZWFkZXJQb2xpY3ksIHR5cGUgSGVhZGVyUG9saWN5IH0gZnJvbSBcIi4vaGVhZGVycy50c1wiO1xuaW1wb3J0IHR5cGUgeyBBdXRoR2F0ZUFwaSB9IGZyb20gXCIuL3BsdWdpbi50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwidHVubmVsOmdhdGVcIik7XG5cbnR5cGUgV2ViUmVxdWVzdElucHV0ID0gSW5jb21pbmdNZXNzYWdlICYge1xuICBib2R5PzogdW5rbm93bjtcbiAgb3JpZ2luYWxVcmw/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgY29uc3QgQVVUSF9QUkVGSVggPSBcIi9hcGkvZW1haWwvYXV0aFwiO1xuXG4vKiogT3B0aW9ucyBmb3Ige0BsaW5rIG1vdW50R2F0ZX0uICovXG5leHBvcnQgaW50ZXJmYWNlIEdhdGVPcHRpb25zIHtcbiAgLyoqIFRoZSBpbi1wcm9jZXNzIGdhdGUgQVBJIChzZXNzaW9uL3JlcXVlc3QvdmVyaWZ5L3N0YXR1cykuICovXG4gIGdhdGU6IEF1dGhHYXRlQXBpO1xuICAvKipcbiAgICogVGhlIHB1YmxpYyBgPHN1YmRvbWFpbj4uPHNlcnZlcj5gIHRoYXQgaWRlbnRpZmllcyBwb3J0ciB0cmFmZmljIGJ5IGBIb3N0YC5cbiAgICogV2hlbiBhYnNlbnQsIG5vIHJlcXVlc3QgaXMgZXZlciBjbGFzc2lmaWVkIGFzIHR1bm5lbCB0cmFmZmljIGFuZCB0aGUgZ2F0ZSBpc1xuICAgKiBpbmVydCAoZXZlcnl0aGluZyBwYXNzZXMgdGhyb3VnaCkgLSBhIHR1bm5lbCB3aXRoIG5vIHB1YmxpYyBkb21haW4gZ2F0ZXNcbiAgICogbm90aGluZy5cbiAgICovXG4gIHB1YmxpY0RvbWFpbj86IHN0cmluZyB8IHJlYWRvbmx5IHN0cmluZ1tdO1xuICAvKipcbiAgICogRXh0cmEgYHgtYCByZXF1ZXN0IGhlYWRlcnMgdHVubmVsIHRyYWZmaWMgbWF5IGZvcndhcmQgKHVuaW9uZWQgd2l0aCB0aGVcbiAgICogYnVpbHQtaW4gYWxsb3ctbGlzdCkuIEV2ZXJ5IG90aGVyIGB4LWAgaGVhZGVyIGlzIHN0cmlwcGVkIGZyb20gdHVubmVsIHRyYWZmaWMuXG4gICAqL1xuICBmb3J3YXJkSGVhZGVycz86IHJlYWRvbmx5IHN0cmluZ1tdO1xuICAvKipcbiAgICogUGF0aCBwcmVmaXhlcyB0aGF0IHJlcXVpcmUgYSB2YWxpZCBzZXNzaW9uLCBiZXlvbmQgdGhlIGJ1aWx0LWluIGAvYXBpL2AuXG4gICAqIFRoZSBkZWZhdWx0IGdhdGluZyBtb2RlbCBhc3N1bWVzIGEgc2VsZi1wcm90ZWN0aW5nIFNQQTogc3RhdGljIGxvYWRzIGZyZWVseVxuICAgKiBzbyB0aGUgYXBwIGNhbiByZW5kZXIsIGFuZCBvbmx5IGAvYXBpLypgIGlzIGdhdGVkLiBBbiBhcHAgd2hvc2UgcHJpdmlsZWdlZFxuICAgKiBzdXJmYWNlIGlzIE5PVCB1bmRlciBgL2FwaS9gIChlLmcuIGEgV2ViU29ja2V0IGF0IGAvd3NgKSBsaXN0cyB0aG9zZSBwcmVmaXhlc1xuICAgKiBoZXJlIHNvIHRoZXkgYXJlIGdhdGVkIHRvby4gTG9naW4gcm91dGVzIChgQVVUSF9QUkVGSVhgKSBhcmUgYWx3YXlzIG9wZW4uXG4gICAqL1xuICBnYXRlUGF0aHM/OiByZWFkb25seSBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBUcnVlIHdoZW4gdGhlIHJlcXVlc3QncyBgSG9zdGAgaXMgb25lIG9mIHRoZSB0dW5uZWwncyBwdWJsaWMgZG9tYWlucyAtIGkuZS4gaXRcbiAqIGNhbWUgaW4gb3ZlciBQb3J0ciBvciBGUlAuIENhc2UtaW5zZW5zaXRpdmU7IHRoZSBvcHRpb25hbCBgOnBvcnRgIGlzIGlnbm9yZWQuXG4gKiBXaGVuIG5vIHB1YmxpYyBkb21haW4gaXMgY29uZmlndXJlZCwgbm90aGluZyBpcyB0dW5uZWwgdHJhZmZpYy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVHVubmVsSG9zdChcbiAgcmVxOiBJbmNvbWluZ01lc3NhZ2UsXG4gIHB1YmxpY0RvbWFpbjogc3RyaW5nIHwgcmVhZG9ubHkgc3RyaW5nW10gfCB1bmRlZmluZWQsXG4pOiBib29sZWFuIHtcbiAgaWYgKCFwdWJsaWNEb21haW4pIHJldHVybiBmYWxzZTtcbiAgY29uc3QgaG9zdCA9IChyZXEuaGVhZGVycy5ob3N0ID8/IFwiXCIpLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCI6XCIpWzBdO1xuICBjb25zdCBkb21haW5zID0gdHlwZW9mIHB1YmxpY0RvbWFpbiA9PT0gXCJzdHJpbmdcIiA/IFtwdWJsaWNEb21haW5dIDogcHVibGljRG9tYWluO1xuICByZXR1cm4gZG9tYWlucy5zb21lKChkb21haW4pID0+IGhvc3QgPT09IGRvbWFpbi50b0xvd2VyQ2FzZSgpLnNwbGl0KFwiOlwiKVswXSk7XG59XG5cbi8qKlxuICogQ2xpZW50IElQIGZvciByYXRlLWxpbWl0aW5nOiB0aGUgUklHSFRNT1NUIGB4LWZvcndhcmRlZC1mb3JgIGVudHJ5ICh0aGUgdmFsdWVcbiAqIHRoZSBuZWFyZXN0IHRydXN0ZWQgaG9wIC0gcG9ydHIgLSB3cm90ZSksIGVsc2UgdGhlIHNvY2tldCBhZGRyZXNzLiBSZWFkaW5nIHRoZVxuICogcmlnaHRtb3N0LCBub3QgdGhlIGxlZnRtb3N0LCBzdG9wcyBhIGNhbGxlciBtaW50aW5nIGEgZnJlc2ggcmF0ZS1saW1pdCBidWNrZXQgYnlcbiAqIHZhcnlpbmcgdGhlIGhlYWRlci4gQ2FsbGVkIGJlZm9yZSB7QGxpbmsgc3RyaXBIZWFkZXJzfS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsaWVudElwKHJlcTogSW5jb21pbmdNZXNzYWdlKTogc3RyaW5nIHtcbiAgY29uc3QgZm9yd2FyZGVkID0gcmVxLmhlYWRlcnNbXCJ4LWZvcndhcmRlZC1mb3JcIl07XG4gIGNvbnN0IGNoYWluID0gKEFycmF5LmlzQXJyYXkoZm9yd2FyZGVkKSA/IGZvcndhcmRlZC5qb2luKFwiLFwiKSA6IChmb3J3YXJkZWQgPz8gXCJcIikpXG4gICAgLnNwbGl0KFwiLFwiKVxuICAgIC5tYXAoKGVudHJ5KSA9PiBlbnRyeS50cmltKCkpXG4gICAgLmZpbHRlcihCb29sZWFuKTtcbiAgcmV0dXJuIGNoYWluLmF0KC0xKSA/PyByZXEuc29ja2V0LnJlbW90ZUFkZHJlc3MgPz8gXCJ1bmtub3duXCI7XG59XG5cbi8qKlxuICogUmVtb3ZlIHRoZSBnYXRlJ3Mgc2Vzc2lvbiBjb29raWUgZnJvbSB0aGUgYENvb2tpZWAgaGVhZGVyIGJlZm9yZSB0aGUgYXBwJ3NcbiAqIGhhbmRsZXJzIHJ1biwgc28gdGhlIGFwcCBuZXZlciBzZWVzIGBkYnhfYXV0aGAgKGl0IGlzIHRoZSBnYXRlJ3MgY29uY2VybikuXG4gKiBQcmVzZXJ2ZXMgb3RoZXIgY29va2llczsgZGVsZXRlcyB0aGUgaGVhZGVyIHdoZW4gaXQgYmVjb21lcyBlbXB0eS5cbiAqL1xuZnVuY3Rpb24gc3RyaXBTZXNzaW9uQ29va2llKHJlcTogSW5jb21pbmdNZXNzYWdlKTogdm9pZCB7XG4gIGNvbnN0IHJhdyA9IHJlcS5oZWFkZXJzLmNvb2tpZTtcbiAgaWYgKCFyYXcpIHJldHVybjtcbiAgY29uc3Qga2VwdCA9IHJhd1xuICAgIC5zcGxpdChcIjtcIilcbiAgICAubWFwKChjKSA9PiBjLnRyaW0oKSlcbiAgICAuZmlsdGVyKChjKSA9PiBjICYmICFjLnN0YXJ0c1dpdGgoXCJkYngtdG9vbHMtYXV0aD1cIikgJiYgIWMuc3RhcnRzV2l0aChcImRieC10b29scy1wYXNza2V5PVwiKSk7XG4gIGlmIChrZXB0Lmxlbmd0aCkgcmVxLmhlYWRlcnMuY29va2llID0ga2VwdC5qb2luKFwiOyBcIik7XG4gIGVsc2UgZGVsZXRlIHJlcS5oZWFkZXJzLmNvb2tpZTtcbn1cblxuLyoqXG4gKiBQcmVzZW50IGEgcGFzc3dvcmRsZXNzLWF1dGhlbnRpY2F0ZWQgY2FsbGVyIHRvIHRoZSBhcHAgdGhlIFNBTUUgd2F5IGEgcGxhdGZvcm0gZnJvbnRcbiAqIGRvb3IgZG9lczogc2V0IHRoZSBmcm9udC1kb29yIGlkZW50aXR5IGhlYWRlcnMgdG8gdGhlIHZlcmlmaWVkIGFkZHJlc3MgKEFwcEtpdFxuICogcmVhZHMge0BsaW5rIHRva2VuLlVTRVJfSURfSEVBREVSfSBmb3IgdGhlIE9CTyB1c2VyIGlkKSwgc28gdGhlIGFwcCBuZWVkcyBub1xuICogZ2F0ZS1zcGVjaWZpYyBjb2RlIHBhdGguXG4gKlxuICogV2hhdCB0aGUgZ2F0ZSBDQU5OT1Qgc2V0IGlzIHtAbGluayB0b2tlbi5BQ0NFU1NfVE9LRU5fSEVBREVSfTogYW4gYXV0aCBzZXNzaW9uXG4gKiBwcm92ZXMgYW4gZW1haWwsIG5vdCBwb3NzZXNzaW9uIG9mIGEgRGF0YWJyaWNrcyBjcmVkZW50aWFsLiBJdHMgYWJzZW5jZSBpcyB3aGF0XG4gKiBgQGRieC10b29scy9hcHBraXRgJ3MgYGlkZW50aXR5OiBcImF1dG9cImAgZGV0ZWN0cywgc28gYSBnYXRlZCByZXF1ZXN0IHJ1bnMgYXMgdGhlXG4gKiBhcHAgc2VydmljZSBwcmluY2lwYWwgaW5zdGVhZCBvZiB0aHJvd2luZy5cbiAqL1xuZnVuY3Rpb24gaW5qZWN0SWRlbnRpdHkocmVxOiBJbmNvbWluZ01lc3NhZ2UsIGVtYWlsOiBzdHJpbmcpOiB2b2lkIHtcbiAgcmVxLmhlYWRlcnNbdG9rZW4uVVNFUl9JRF9IRUFERVJdID0gZW1haWw7XG4gIHJlcS5oZWFkZXJzW3Rva2VuLlVTRVJfRU1BSUxfSEVBREVSXSA9IGVtYWlsO1xufVxuXG4vKiogUmVhZCB0aGUgcmF3IHJlcXVlc3QgYm9keSBhcyB0ZXh0IChBcHBLaXQgcGFyc2VzIEpTT04sIGJ1dCB0aGUgZ2F0ZSByb3V0ZXNcbiAqIGFyZSBtb3VudGVkIGJlZm9yZSB0aGF0IHJ1bnMgZm9yIHR1bm5lbCB0cmFmZmljLCBzbyByZWFkIGRlZmVuc2l2ZWx5KS4gKi9cbmZ1bmN0aW9uIHJlYWRCb2R5KHJlcTogV2ViUmVxdWVzdElucHV0KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgLy8gQXBwS2l0J3MganNvbiBib2R5LXBhcnNlciBtYXkgaGF2ZSBhbHJlYWR5IHBvcHVsYXRlZCByZXEuYm9keTsgcHJlZmVyIGl0LlxuICBpZiAocmVxLmJvZHkgIT09IHVuZGVmaW5lZCAmJiByZXEuYm9keSAhPT0gbnVsbCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodHlwZW9mIHJlcS5ib2R5ID09PSBcInN0cmluZ1wiID8gcmVxLmJvZHkgOiBKU09OLnN0cmluZ2lmeShyZXEuYm9keSkpO1xuICB9XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIGxldCBkYXRhID0gXCJcIjtcbiAgICByZXEub24oXCJkYXRhXCIsIChjaHVuaykgPT4gKGRhdGEgKz0gY2h1bmspKTtcbiAgICByZXEub24oXCJlbmRcIiwgKCkgPT4gcmVzb2x2ZShkYXRhKSk7XG4gICAgcmVxLm9uKFwiZXJyb3JcIiwgKCkgPT4gcmVzb2x2ZShkYXRhKSk7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd2ViSGVhZGVycyhyZXE6IEluY29taW5nTWVzc2FnZSk6IEhlYWRlcnMge1xuICBjb25zdCBoZWFkZXJzID0gbmV3IEhlYWRlcnMoKTtcbiAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHJlcS5oZWFkZXJzKSkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHZhbHVlKSBoZWFkZXJzLmFwcGVuZChuYW1lLCBpdGVtKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGhlYWRlcnMuc2V0KG5hbWUsIHZhbHVlKTtcbiAgICB9XG4gIH1cbiAgaGVhZGVycy5zZXQoXCJ4LXJlYWwtaXBcIiwgY2xpZW50SXAocmVxKSk7XG4gIHJldHVybiBoZWFkZXJzO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd2ViUmVxdWVzdChyZXE6IFdlYlJlcXVlc3RJbnB1dCk6IFByb21pc2U8Z2xvYmFsVGhpcy5SZXF1ZXN0PiB7XG4gIGNvbnN0IGhvc3QgPSByZXEuaGVhZGVycy5ob3N0ID8/IFwibG9jYWxob3N0XCI7XG4gIGNvbnN0IGhvc3RuYW1lID0gaG9zdC5zcGxpdChcIjpcIilbMF0/LnRvTG93ZXJDYXNlKCk7XG4gIGNvbnN0IHByb3RvY29sID0gaG9zdG5hbWUgPT09IFwibG9jYWxob3N0XCIgfHwgaG9zdG5hbWUgPT09IFwiMTI3LjAuMC4xXCIgPyBcImh0dHBcIiA6IFwiaHR0cHNcIjtcbiAgY29uc3QgbWV0aG9kID0gKHJlcS5tZXRob2QgPz8gXCJHRVRcIikudG9VcHBlckNhc2UoKTtcbiAgY29uc3QgYm9keSA9IG1ldGhvZCA9PT0gXCJHRVRcIiB8fCBtZXRob2QgPT09IFwiSEVBRFwiID8gdW5kZWZpbmVkIDogYXdhaXQgcmVhZEJvZHkocmVxKTtcbiAgcmV0dXJuIG5ldyBnbG9iYWxUaGlzLlJlcXVlc3QoYCR7cHJvdG9jb2x9Oi8vJHtob3N0fSR7cmVxLm9yaWdpbmFsVXJsIHx8IHJlcS51cmx9YCwge1xuICAgIG1ldGhvZCxcbiAgICBoZWFkZXJzOiB3ZWJIZWFkZXJzKHJlcSksXG4gICAgLi4uKGJvZHkgPyB7IGJvZHkgfSA6IHt9KSxcbiAgfSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kV2ViUmVzcG9uc2UocmVzOiBSZXNwb25zZSwgcmVzcG9uc2U6IGdsb2JhbFRoaXMuUmVzcG9uc2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIHJlc3BvbnNlLmhlYWRlcnMuZW50cmllcygpKSB7XG4gICAgaWYgKG5hbWUudG9Mb3dlckNhc2UoKSAhPT0gXCJzZXQtY29va2llXCIpIHJlcy5zZXRIZWFkZXIobmFtZSwgdmFsdWUpO1xuICB9XG4gIGNvbnN0IGNvb2tpZXMgPSByZXNwb25zZS5oZWFkZXJzLmdldFNldENvb2tpZSgpO1xuICBpZiAoY29va2llcy5sZW5ndGgpIHJlcy5zZXRIZWFkZXIoXCJzZXQtY29va2llXCIsIGNvb2tpZXMpO1xuICBjb25zdCBib2R5ID0gQnVmZmVyLmZyb20oYXdhaXQgcmVzcG9uc2UuYXJyYXlCdWZmZXIoKSk7XG4gIHJlcy5zdGF0dXMocmVzcG9uc2Uuc3RhdHVzKS5zZW5kKGJvZHkpO1xufVxuXG4vKipcbiAqIFdoYXQgdGhlIGNhbGxlciBzaG91bGQgZG8gd2l0aCBhIHJlcXVlc3QsIGZyb20ge0BsaW5rIGdhdGVSZXF1ZXN0fS5cbiAqXG4gKiAgIC0gYHBhc3NgIC0gbm90IHR1bm5lbCB0cmFmZmljLCBvciBhbiBvcGVuIGxvZ2luIHJvdXRlLiBGb3J3YXJkIHVudG91Y2hlZC5cbiAqICAgLSBgYWxsb3dgIC0gdHVubmVsIHRyYWZmaWMgdGhhdCBpcyBhdXRob3JpemVkLiBUaGUgcmVxdWVzdCdzIGhlYWRlcnMgaGF2ZVxuICogICAgIEFMUkVBRFkgYmVlbiByZXdyaXR0ZW4gKHBvbGljeSBhcHBsaWVkLCBpZGVudGl0eSBpbmplY3RlZCwgc2Vzc2lvbiBjb29raWVcbiAqICAgICBzdHJpcHBlZCksIHNvIGZvcndhcmQgaXQgYXMgaXQgbm93IHN0YW5kcy5cbiAqICAgLSBgZGVueWAgLSB0dW5uZWwgdHJhZmZpYyB3aXRoIG5vIHZhbGlkIHNlc3Npb24uIEFuc3dlciBgNDAxYCB3aXRoXG4gKiAgICAge0BsaW5rIEFVVEhfUFJFRklYfSBhcyB0aGUgbG9naW4gcGF0aC5cbiAqL1xuZXhwb3J0IHR5cGUgR2F0ZUFjdGlvbiA9IFwicGFzc1wiIHwgXCJhbGxvd1wiIHwgXCJkZW55XCI7XG5cbi8qKlxuICogVEhFIGdhdGluZyBkZWNpc2lvbiwgZm9yIG9uZSByZXF1ZXN0LCBpbmRlcGVuZGVudCBvZiBob3cgaXQgd2lsbCBiZSBhbnN3ZXJlZC5cbiAqXG4gKiBCb3RoIHBhdGhzIGNhbGwgdGhpczogdGhlIEV4cHJlc3MgbWlkZGxld2FyZSBiZWxvdyAod2hlcmUgdGhlIGFwcCBpcyB0aGVcbiAqIHByb2Nlc3MpIGFuZCBgQGRieC10b29scy9jbGktdHVubmVsYCdzIHJldmVyc2UgcHJveHkgKHdoZXJlIHRoZSBhcHAgaXMgYSBjaGlsZFxuICogcHJvY2VzcyBvbiBhIHByaXZhdGUgcG9ydCkuIEEgZGl2ZXJnZW5jZSBiZXR3ZWVuIHRoZW0gd291bGQgYmUgYSBzZWN1cml0eSBidWdcbiAqIHRoZSBzZWNvbmQgcGF0aCBjb3VsZCBub3QgYmUgdGVzdGVkIGludG8gYWdyZWVtZW50IC0gb25lIHBhdGggZm9yZ2V0dGluZyB0b1xuICogc3RyaXAgYHgtZm9yd2FyZGVkLWFjY2Vzcy10b2tlbmAgaXMgZW5vdWdoIC0gc28gdGhlIGRlY2lzaW9uLCB0aGUgaGVhZGVyXG4gKiByZXdyaXRpbmcsIGFuZCB0aGUgaWRlbnRpdHkgaW5qZWN0aW9uIGxpdmUgaGVyZSBvbmNlIGFuZCB0aGUgdHJhbnNwb3J0cyBvbmx5XG4gKiBkaWZmZXIgaW4gaG93IHRoZXkgV1JJVEUgdGhlIG91dGNvbWUuXG4gKlxuICogTXV0YXRlcyBgcmVxLmhlYWRlcnNgIG9uIHRoZSBgYWxsb3dgL2BwYXNzYC13aXRoLWNvb2tpZSBwYXRocywgd2hpY2ggaXMgZXhhY3RseVxuICogd2hhdCBib3RoIGNhbGxlcnMgd2FudDogRXhwcmVzcyBoYW5kcyB0aGUgc2FtZSBvYmplY3QgdG8gdGhlIGFwcCdzIGhhbmRsZXJzLCBhbmRcbiAqIHRoZSBwcm94eSBmb3J3YXJkcyBpdCB1cHN0cmVhbS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdhdGVSZXF1ZXN0KFxuICByZXE6IEluY29taW5nTWVzc2FnZSxcbiAgb3B0aW9uczogR2F0ZU9wdGlvbnMgJiB7IGhlYWRlclBvbGljeT86IEhlYWRlclBvbGljeSB9LFxuKTogUHJvbWlzZTxHYXRlQWN0aW9uPiB7XG4gIGNvbnN0IHsgZ2F0ZSwgcHVibGljRG9tYWluIH0gPSBvcHRpb25zO1xuICAvLyBOb3QgdHVubmVsIHRyYWZmaWMgKHBsYXRmb3JtIGZyb250IGRvb3IsIG9yIGFueSBvdGhlciBsb2NhbCBjYWxsZXIpOiB0aGVcbiAgLy8gcmVxdWVzdCBpcyBhbHJlYWR5IGF1dGhlbnRpY2F0ZWQsIG9yIGlzIG5vdCBvdXJzIHRvIGdhdGUuXG4gIGlmICghaXNUdW5uZWxIb3N0KHJlcSwgcHVibGljRG9tYWluKSkgcmV0dXJuIFwicGFzc1wiO1xuXG4gIGNvbnN0IHBhdGggPSAocmVxLnVybCA/PyBcIi9cIikuc3BsaXQoXCI/XCIpWzBdID8/IFwiL1wiO1xuICAvLyBUaGUgbG9naW4gZmxvdyBpcyBvcGVuIHNvIHRoZSBicm93c2VyIGNhbiByZW5kZXIgPEF1dGhHYXRlPiBhbmQgc2lnbiBpbi5cbiAgaWYgKHBhdGguc3RhcnRzV2l0aChBVVRIX1BSRUZJWCkpIHJldHVybiBcInBhc3NcIjtcblxuICAvLyBBbnRpLXNwb29mOiBvbmx5IHRoZSBnYXRlIG1heSBhc3NlcnQgaWRlbnRpdHkgb24gdHVubmVsIHRyYWZmaWMuXG4gIGNvbnN0IHBvbGljeSA9IG9wdGlvbnMuaGVhZGVyUG9saWN5ID8/IHRvSGVhZGVyUG9saWN5KG9wdGlvbnMuZm9yd2FyZEhlYWRlcnMpO1xuICBjb25zdCByZW1vdmVkID0gcG9saWN5LmFwcGx5KHJlcS5oZWFkZXJzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTtcbiAgaWYgKHJlbW92ZWQubGVuZ3RoKSBsb2dnZXIuZGVidWcoXCJzdHJpcHBlZCBpbmJvdW5kIGhlYWRlcnNcIiwgeyByZW1vdmVkIH0pO1xuXG4gIGNvbnN0IGdhdGVQYXRocyA9IG9wdGlvbnMuZ2F0ZVBhdGhzID8/IFtdO1xuICAvLyBBIHBhdGggaXMgZ2F0ZWQgaWYgaXQgaXMgdW5kZXIgYC9hcGkvYCBvciBhbnkgY2FsbGVyLXN1cHBsaWVkIHByZWZpeCAoZS5nLlxuICAvLyBgL3dzYCBmb3IgYSBXZWJTb2NrZXQgYXBwKS5cbiAgY29uc3QgZ2F0ZWQgPVxuICAgIHBhdGguc3RhcnRzV2l0aChcIi9hcGkvXCIpIHx8XG4gICAgZ2F0ZVBhdGhzLnNvbWUoKHByZWZpeCkgPT4gcGF0aCA9PT0gcHJlZml4IHx8IHBhdGguc3RhcnRzV2l0aChgJHtwcmVmaXh9L2ApKTtcblxuICAvLyBBcHAtZ2F0aW5nIG1vZGU6IHdoZW4gYGdhdGVQYXRoc2AgaXMgc2V0IHRoZSBjYWxsZXIgaXMgZnJvbnRpbmcgYSB3aG9sZSBhcHBcbiAgLy8gKG5vdCBhIHNlbGYtcHJvdGVjdGluZyBTUEEpLCBzbyBhbiB1bmF1dGhlbnRpY2F0ZWQgdG9wLWxldmVsIGJyb3dzZXJcbiAgLy8gbmF2aWdhdGlvbiBpcyBkZW5pZWQgdG9vIOKAlCB0aGUgdHJhbnNwb3J0IGFuc3dlcnMgaXQgd2l0aCB0aGUgaG9zdGVkIGxvZ2luXG4gIC8vIHBhZ2UsIHB1dHRpbmcgc2lnbi1pbiBpbiBmcm9udCBvZiB0aGUgYXBwIGluc3RlYWQgb2YgbG9hZGluZyBpdHMgc2hlbGwgd2l0aFxuICAvLyBhIGRlYWQgZ2F0ZWQgcmVxdWVzdC4gTm9uLW5hdmlnYXRpb24gc3RhdGljIChhc3NldHMpIHN0aWxsIGxvYWRzIGZyZWVseSBzb1xuICAvLyB0aGUgbG9naW4gcGFnZSBhbmQgYXBwIGNhbiByZW5kZXIuXG4gIGNvbnN0IGFwcEdhdGluZyA9IGdhdGVQYXRocy5sZW5ndGggPiAwO1xuICBjb25zdCBtdXN0QXV0aCA9IGdhdGVkIHx8IChhcHBHYXRpbmcgJiYgd2FudHNMb2dpblBhZ2UocmVxKSk7XG4gIGlmICghbXVzdEF1dGgpIHtcbiAgICBzdHJpcFNlc3Npb25Db29raWUocmVxKTtcbiAgICByZXR1cm4gXCJwYXNzXCI7XG4gIH1cblxuICAvLyBBIGdhdGVkIHJlcXVlc3QgbmVlZHMgYSB2YWxpZCBCZXR0ZXIgQXV0aCBzZXNzaW9uLlxuICBjb25zdCBlbWFpbCA9IGF3YWl0IGdhdGUuc2Vzc2lvbih3ZWJIZWFkZXJzKHJlcSkpO1xuICBpZiAoIWVtYWlsKSByZXR1cm4gXCJkZW55XCI7XG4gIGluamVjdElkZW50aXR5KHJlcSwgZW1haWwpO1xuICBzdHJpcFNlc3Npb25Db29raWUocmVxKTtcbiAgcmV0dXJuIFwiYWxsb3dcIjtcbn1cblxuLyoqIFRoZSBib2R5IG9mIGEgYGRlbnlgLCBzaGFyZWQgc28gYm90aCBwYXRocyBhbnN3ZXIgYSA0MDEgaWRlbnRpY2FsbHkuICovXG5leHBvcnQgY29uc3QgVU5BVVRIT1JJWkVEX0JPRFkgPSB7XG4gIGVycm9yOiBcImF1dGhlbnRpY2F0aW9uIHJlcXVpcmVkXCIsXG4gIGxvZ2luUGF0aDogQVVUSF9QUkVGSVgsXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIFdoZXRoZXIgYSBkZW5pZWQgcmVxdWVzdCBpcyBhIHRvcC1sZXZlbCBCUk9XU0VSIE5BVklHQVRJT04gdGhhdCBzaG91bGQgYmVcbiAqIGFuc3dlcmVkIHdpdGggdGhlIGhvc3RlZCBsb2dpbiBwYWdlIHJhdGhlciB0aGFuIGEgNDAxLlxuICpcbiAqIEFuIGFwcCBmcm9udGVkIGJ5IHRoZSBnYXRlICh2aWEgYGdhdGVQYXRoc2ApIG1heSBzZXJ2ZSBpdHMgb3duIEhUTUwgZnJvbSBhblxuICogdW5nYXRlZCBwYXRoIHdoaWxlIGl0cyBwcml2aWxlZ2VkIHN1cmZhY2UgKGAvd3NgLCBgL2FwaWApIGlzIGdhdGVkLiBBIGJyb3dzZXJcbiAqIG5hdmlnYXRpbmcgdG8gaXQgd291bGQgb3RoZXJ3aXNlIGxvYWQgdGhlIGFwcCBzaGVsbCBhbmQgb25seSBzZWUgdGhlIGdhdGVkXG4gKiByZXF1ZXN0IGZhaWwsIHdpdGggbm8gd2F5IHRvIHNpZ24gaW4uIFNlcnZpbmcgdGhlIGxvZ2luIHBhZ2Ugb24gdGhlIG5hdmlnYXRpb25cbiAqIGl0c2VsZiBwdXRzIHNpZ24taW4gaW4gZnJvbnQgb2YgdGhlIGFwcC4gQXBwbGllcyBvbmx5IHRvIEdFVCByZXF1ZXN0cyB0aGF0XG4gKiBhY2NlcHQgSFRNTCBhbmQgYXJlIG5vdCBhc2tpbmcgZm9yIHRoZSBsb2dpbiBBUEkgb3IgYW4gYXNzZXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3YW50c0xvZ2luUGFnZShyZXE6IEluY29taW5nTWVzc2FnZSk6IGJvb2xlYW4ge1xuICBjb25zdCBtZXRob2QgPSAocmVxLm1ldGhvZCA/PyBcIkdFVFwiKS50b1VwcGVyQ2FzZSgpO1xuICBpZiAobWV0aG9kICE9PSBcIkdFVFwiICYmIG1ldGhvZCAhPT0gXCJIRUFEXCIpIHJldHVybiBmYWxzZTtcbiAgY29uc3QgcGF0aCA9IChyZXEudXJsID8/IFwiL1wiKS5zcGxpdChcIj9cIilbMF0gPz8gXCIvXCI7XG4gIGlmIChwYXRoLnN0YXJ0c1dpdGgoQVVUSF9QUkVGSVgpKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IGFjY2VwdCA9IFN0cmluZyhyZXEuaGVhZGVycy5hY2NlcHQgPz8gXCJcIik7XG4gIHJldHVybiBhY2NlcHQuaW5jbHVkZXMoXCJ0ZXh0L2h0bWxcIik7XG59XG5cbi8qKlxuICogUmVnaXN0ZXIgdGhlIGxvZ2luIHJvdXRlcyBhbmQgdGhlIGdhdGluZyBtaWRkbGV3YXJlIG9uIHRoZSBhcHAncyBFeHByZXNzXG4gKiBpbnN0YW5jZS4gQ2FsbGVkIGZyb20ge0BsaW5rIEF1dGhHYXRlUGx1Z2lufSB3aXRoIHRoZSByb3V0ZXIgQXBwS2l0IGhhbmRzXG4gKiBgaW5qZWN0Um91dGVzYCwgcGx1cyBgdGhpcy5jb250ZXh0LmFkZE1pZGRsZXdhcmVgIGZvciB0aGUgZ2xvYmFsIGdhdGUuXG4gKlxuICogYGFkZFJvdXRlYC9gYWRkTWlkZGxld2FyZWAgYXJlIHVzZWQgKHZpYSB0aGUgcGFzc2VkIGNhbGxiYWNrcykgYmVjYXVzZSB0aGUgbG9naW5cbiAqIHJvdXRlcyBsaXZlIGF0IGFuIEFCU09MVVRFIHBhdGggKGAvYXBpL2VtYWlsL2F1dGgvKmAsIHRoZSBjbGllbnQncyBjb250cmFjdCksXG4gKiBub3QgdW5kZXIgdGhlIHBsdWdpbidzIGAvYXBpL2F1dGhHYXRlYCBiYXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbW91bnRHYXRlKFxuICBvcHRzOiBHYXRlT3B0aW9ucyxcbiAgX2FkZFJvdXRlOiAobWV0aG9kOiBcImdldFwiIHwgXCJwb3N0XCIsIHBhdGg6IHN0cmluZywgaGFuZGxlcjogUmVxdWVzdEhhbmRsZXIpID0+IHZvaWQsXG4gIGFkZE1pZGRsZXdhcmU6IChwYXRoOiBzdHJpbmcsIGhhbmRsZXI6IFJlcXVlc3RIYW5kbGVyKSA9PiB2b2lkLFxuKTogdm9pZCB7XG4gIGNvbnN0IHsgZ2F0ZSwgcHVibGljRG9tYWluLCBmb3J3YXJkSGVhZGVycywgZ2F0ZVBhdGhzIH0gPSBvcHRzO1xuICBjb25zdCBoZWFkZXJQb2xpY3kgPSB0b0hlYWRlclBvbGljeShmb3J3YXJkSGVhZGVycyk7XG4gIGxvZ2dlci5kZWJ1ZyhcImdhdGUgbW91bnRlZFwiLCB7IHB1YmxpY0RvbWFpbiwgZm9yd2FyZDogaGVhZGVyUG9saWN5LnBhdHRlcm5zLCBnYXRlUGF0aHMgfSk7XG5cbiAgLy8gQmV0dGVyIEF1dGggYW5kIHRoZSBjb21wYXRpYmlsaXR5IHJvdXRlcyBzaGFyZSBvbmUgZmV0Y2gtY29tcGF0aWJsZVxuICAvLyBoYW5kbGVyIGluIGJvdGggaG9zdGluZyBtb2Rlcy5cbiAgY29uc3QgYXV0aEhhbmRsZXIgPSAoYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgaWYgKCFpc1R1bm5lbEhvc3QocmVxLCBwdWJsaWNEb21haW4pKSB7XG4gICAgICBjb25zdCBwYXRoID0gKHJlcS51cmwgPz8gXCIvXCIpLnNwbGl0KFwiP1wiKVswXSA/PyBcIi9cIjtcbiAgICAgIGlmIChwYXRoLmVuZHNXaXRoKFwiL3N0YXR1c1wiKSkge1xuICAgICAgICByZXMuc3RhdHVzKDIwMCkuanNvbih7IGF1dGhlbnRpY2F0ZWQ6IGZhbHNlLCBlbmFibGVkOiBmYWxzZSwgcGFzc2tleXNFbmFibGVkOiBmYWxzZSB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDA0KS5qc29uKHsgZXJyb3I6IFwibm90IGZvdW5kXCIgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGF3YWl0IHNlbmRXZWJSZXNwb25zZShyZXMsIGF3YWl0IGdhdGUuaGFuZGxlcihhd2FpdCB3ZWJSZXF1ZXN0KHJlcSkpKTtcbiAgfSkgYXMgUmVxdWVzdEhhbmRsZXI7XG4gIGFkZE1pZGRsZXdhcmUoQVVUSF9QUkVGSVgsIGF1dGhIYW5kbGVyKTtcblxuICAvLyAtLS0gVGhlIGdhdGUgbWlkZGxld2FyZSAocnVucyBiZWZvcmUgc3RhdGljICsgdGhlIGFwcCdzIC9hcGkgaGFuZGxlcnMpIC0tLVxuXG4gIGNvbnN0IGdhdGVNaWRkbGV3YXJlID0gKGFzeW5jIChyZXEsIHJlcywgbmV4dCkgPT4ge1xuICAgIGNvbnN0IGFjdGlvbiA9IGF3YWl0IGdhdGVSZXF1ZXN0KHJlcSwgeyBnYXRlLCBwdWJsaWNEb21haW4sIGhlYWRlclBvbGljeSwgZ2F0ZVBhdGhzIH0pO1xuICAgIGlmIChhY3Rpb24gPT09IFwiZGVueVwiKSByZXMuc3RhdHVzKDQwMSkuanNvbihVTkFVVEhPUklaRURfQk9EWSk7XG4gICAgZWxzZSBuZXh0KCk7XG4gIH0pIGFzIFJlcXVlc3RIYW5kbGVyO1xuXG4gIGFkZE1pZGRsZXdhcmUoXCIvXCIsIGdhdGVNaWRkbGV3YXJlKTtcbn1cbiJdfQ==
|
package/lib/src/interceptor.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `tunnelInterceptor()` - the {@link Interceptor} that fronts an app with a public
|
|
3
|
-
* portr tunnel, consuming the {@link InterceptorContext} `@dbx-tools/appkit`'s
|
|
3
|
+
* portr and/or frp tunnel, consuming the {@link InterceptorContext} `@dbx-tools/appkit`'s
|
|
4
4
|
* `createApp` hands it.
|
|
5
5
|
*
|
|
6
6
|
* The tunnel runs IN-PROCESS: the APP is the main process and hands this interceptor
|
|
@@ -19,7 +19,9 @@
|
|
|
19
19
|
import type { Interceptor } from "@dbx-tools/appkit";
|
|
20
20
|
/** Options for {@link tunnelInterceptor} (each also resolvable from env). */
|
|
21
21
|
export interface TunnelInterceptorOptions {
|
|
22
|
-
/**
|
|
22
|
+
/** Tunnel clients to run. Env `DBX_TOOLS_TUNNEL_TRANSPORT`; defaults to `portr`. */
|
|
23
|
+
transport?: TunnelTransport;
|
|
24
|
+
/** Public host to serve on. Env `TUNNEL_PUBLIC_DOMAIN`. */
|
|
23
25
|
publicDomain?: string;
|
|
24
26
|
/** portr subdomain (else derived from {@link publicDomain}). */
|
|
25
27
|
subdomain?: string;
|
|
@@ -29,13 +31,28 @@ export interface TunnelInterceptorOptions {
|
|
|
29
31
|
* (then `8000`), which is the port the platform routes to.
|
|
30
32
|
*/
|
|
31
33
|
port?: number;
|
|
34
|
+
/** frps control host; defaults to the FRP public domain. Env `FRP_SERVER`. */
|
|
35
|
+
frpServer?: string;
|
|
36
|
+
/** FRP public HTTP host. Env `TUNNEL_FRP_PUBLIC_DOMAIN`. */
|
|
37
|
+
frpPublicDomain?: string;
|
|
38
|
+
/** frps control port. Env `FRP_SERVER_PORT`; defaults to `443`. */
|
|
39
|
+
frpServerPort?: number;
|
|
40
|
+
/** frpc transport protocol. Env `FRP_PROTOCOL`; defaults to `wss`. */
|
|
41
|
+
frpProtocol?: string;
|
|
42
|
+
/** frps auth token. Env `FRP_TOKEN` (or `TUNNEL_TOKEN`). */
|
|
43
|
+
frpToken?: string;
|
|
44
|
+
/** frp proxy registration name. Env `FRP_PROXY_NAME`. */
|
|
45
|
+
frpProxyName?: string;
|
|
32
46
|
}
|
|
47
|
+
/** Public tunnel clients supported by the interceptor and CLI. */
|
|
48
|
+
export type TunnelTransport = "portr" | "frp" | "both";
|
|
49
|
+
/** Resolve and validate the tunnel transport selector. */
|
|
50
|
+
export declare function resolveTunnelTransport(transport?: string): TunnelTransport;
|
|
33
51
|
/**
|
|
34
52
|
* Build the tunnel {@link Interceptor}. Pass it to `createApp({ interceptor })`.
|
|
35
53
|
*
|
|
36
|
-
* A no-op (logs and returns) when
|
|
37
|
-
*
|
|
38
|
-
* unconditionally and only actually tunnels where the deployment wired portr.
|
|
54
|
+
* A no-op (logs and returns) when none of the selected tunnel clients resolve
|
|
55
|
+
* usable configuration, so an app can register it unconditionally.
|
|
39
56
|
*
|
|
40
57
|
* @example
|
|
41
58
|
* import { appkit } from "@dbx-tools/appkit";
|