@betterportal/tunnels 1.0.24 → 1.0.26

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.
Files changed (160) hide show
  1. package/lib/.bsb/clients/service-tunnels-client.d.ts +133 -0
  2. package/lib/.bsb/clients/service-tunnels-client.d.ts.map +1 -0
  3. package/lib/.bsb/clients/service-tunnels-client.js +102 -0
  4. package/lib/.bsb/clients/service-tunnels-client.js.map +1 -0
  5. package/lib/.bsb/clients/service-tunnels-proxy.d.ts +43 -0
  6. package/lib/.bsb/clients/service-tunnels-proxy.d.ts.map +1 -0
  7. package/lib/.bsb/clients/service-tunnels-proxy.js +47 -0
  8. package/lib/.bsb/clients/service-tunnels-proxy.js.map +1 -0
  9. package/lib/auth.d.ts +12 -0
  10. package/lib/auth.d.ts.map +1 -0
  11. package/lib/auth.js +59 -0
  12. package/lib/auth.js.map +1 -0
  13. package/lib/cli.d.ts +2 -0
  14. package/lib/cli.d.ts.map +1 -0
  15. package/lib/cli.js +406 -0
  16. package/lib/cli.js.map +1 -0
  17. package/lib/generated/prisma/client.d.ts +1 -0
  18. package/lib/generated/prisma/client.js +5 -0
  19. package/lib/generated/prisma/default.d.ts +1 -0
  20. package/lib/generated/prisma/default.js +5 -0
  21. package/lib/generated/prisma/edge.d.ts +1 -0
  22. package/lib/generated/prisma/edge.js +278 -0
  23. package/lib/generated/prisma/index-browser.js +304 -0
  24. package/lib/generated/prisma/index.d.ts +13885 -0
  25. package/lib/generated/prisma/index.js +278 -0
  26. package/lib/generated/prisma/package.json +144 -0
  27. package/lib/generated/prisma/query_compiler_fast_bg.js +2 -0
  28. package/lib/generated/prisma/query_compiler_fast_bg.wasm +0 -0
  29. package/lib/generated/prisma/query_compiler_fast_bg.wasm-base64.js +2 -0
  30. package/lib/generated/prisma/runtime/client.d.ts +3386 -0
  31. package/lib/generated/prisma/runtime/client.js +86 -0
  32. package/lib/generated/prisma/runtime/index-browser.d.ts +90 -0
  33. package/lib/generated/prisma/runtime/index-browser.js +6 -0
  34. package/lib/generated/prisma/runtime/wasm-compiler-edge.js +76 -0
  35. package/lib/generated/prisma/schema.prisma +142 -0
  36. package/lib/generated/prisma/wasm-edge-light-loader.mjs +5 -0
  37. package/lib/generated/prisma/wasm-worker-loader.mjs +5 -0
  38. package/lib/plugins/service-tunnels-admin/.bp-generated/registry.d.ts +3 -0
  39. package/lib/plugins/service-tunnels-admin/.bp-generated/registry.d.ts.map +1 -0
  40. package/lib/plugins/service-tunnels-admin/.bp-generated/registry.js +152 -0
  41. package/lib/plugins/service-tunnels-admin/.bp-generated/registry.js.map +1 -0
  42. package/lib/plugins/service-tunnels-admin/.bp-generated/route-runtime.d.ts +9 -0
  43. package/lib/plugins/service-tunnels-admin/.bp-generated/route-runtime.d.ts.map +1 -0
  44. package/lib/plugins/service-tunnels-admin/.bp-generated/route-runtime.js +6 -0
  45. package/lib/plugins/service-tunnels-admin/.bp-generated/route-runtime.js.map +1 -0
  46. package/lib/plugins/service-tunnels-admin/assets/brand/bettertunnels-horizontal-light.svg +18 -0
  47. package/lib/plugins/service-tunnels-admin/assets/brand/bettertunnels-square-dark-1024x1024.png +0 -0
  48. package/lib/plugins/service-tunnels-admin/assets/brand/favicon.svg +12 -0
  49. package/lib/plugins/service-tunnels-admin/betterportal-logo.png +0 -0
  50. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/GET.d.ts +20 -0
  51. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/GET.d.ts.map +1 -0
  52. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/GET.js +51 -0
  53. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/GET.js.map +1 -0
  54. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/_theme.bootstrap1/GET.d.ts +5 -0
  55. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/_theme.bootstrap1/GET.d.ts.map +1 -0
  56. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/_theme.bootstrap1/GET.js +6 -0
  57. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/_theme.bootstrap1/GET.js.map +1 -0
  58. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/index.d.ts +7 -0
  59. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/index.d.ts.map +1 -0
  60. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/index.js +12 -0
  61. package/lib/plugins/service-tunnels-admin/bp-routes/cli-auth/verify/index.js.map +1 -0
  62. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/GET.d.ts +40 -0
  63. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/GET.d.ts.map +1 -0
  64. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/GET.js +57 -0
  65. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/GET.js.map +1 -0
  66. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/GET.d.ts +6 -0
  67. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/GET.d.ts.map +1 -0
  68. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/GET.js +30 -0
  69. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/GET.js.map +1 -0
  70. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/index.stream.d.ts +6 -0
  71. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/index.stream.d.ts.map +1 -0
  72. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/index.stream.js +9 -0
  73. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/index.stream.js.map +1 -0
  74. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/index.d.ts +7 -0
  75. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/index.d.ts.map +1 -0
  76. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/index.js +14 -0
  77. package/lib/plugins/service-tunnels-admin/bp-routes/dashboard/index.js.map +1 -0
  78. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/GET.d.ts +25 -0
  79. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/GET.d.ts.map +1 -0
  80. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/GET.js +34 -0
  81. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/GET.js.map +1 -0
  82. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/_theme.bootstrap1/GET.d.ts +5 -0
  83. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/_theme.bootstrap1/GET.d.ts.map +1 -0
  84. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/_theme.bootstrap1/GET.js +5 -0
  85. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/_theme.bootstrap1/GET.js.map +1 -0
  86. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/index.d.ts +7 -0
  87. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/index.d.ts.map +1 -0
  88. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/index.js +12 -0
  89. package/lib/plugins/service-tunnels-admin/bp-routes/downloads/index.js.map +1 -0
  90. package/lib/plugins/service-tunnels-admin/bp-routes/landing/GET.d.ts +35 -0
  91. package/lib/plugins/service-tunnels-admin/bp-routes/landing/GET.d.ts.map +1 -0
  92. package/lib/plugins/service-tunnels-admin/bp-routes/landing/GET.js +52 -0
  93. package/lib/plugins/service-tunnels-admin/bp-routes/landing/GET.js.map +1 -0
  94. package/lib/plugins/service-tunnels-admin/bp-routes/landing/_theme.bootstrap1/GET.d.ts +5 -0
  95. package/lib/plugins/service-tunnels-admin/bp-routes/landing/_theme.bootstrap1/GET.d.ts.map +1 -0
  96. package/lib/plugins/service-tunnels-admin/bp-routes/landing/_theme.bootstrap1/GET.js +5 -0
  97. package/lib/plugins/service-tunnels-admin/bp-routes/landing/_theme.bootstrap1/GET.js.map +1 -0
  98. package/lib/plugins/service-tunnels-admin/bp-routes/landing/index.d.ts +7 -0
  99. package/lib/plugins/service-tunnels-admin/bp-routes/landing/index.d.ts.map +1 -0
  100. package/lib/plugins/service-tunnels-admin/bp-routes/landing/index.js +12 -0
  101. package/lib/plugins/service-tunnels-admin/bp-routes/landing/index.js.map +1 -0
  102. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/GET.d.ts +39 -0
  103. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/GET.d.ts.map +1 -0
  104. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/GET.js +46 -0
  105. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/GET.js.map +1 -0
  106. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/_theme.bootstrap1/GET.d.ts +5 -0
  107. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/_theme.bootstrap1/GET.d.ts.map +1 -0
  108. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/_theme.bootstrap1/GET.js +5 -0
  109. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/_theme.bootstrap1/GET.js.map +1 -0
  110. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/index.d.ts +7 -0
  111. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/index.d.ts.map +1 -0
  112. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/index.js +14 -0
  113. package/lib/plugins/service-tunnels-admin/bp-routes/tunnels/index.js.map +1 -0
  114. package/lib/plugins/service-tunnels-admin/brand-assets.d.ts +7 -0
  115. package/lib/plugins/service-tunnels-admin/brand-assets.d.ts.map +1 -0
  116. package/lib/plugins/service-tunnels-admin/brand-assets.js +24 -0
  117. package/lib/plugins/service-tunnels-admin/brand-assets.js.map +1 -0
  118. package/lib/plugins/service-tunnels-admin/index.d.ts +64 -0
  119. package/lib/plugins/service-tunnels-admin/index.d.ts.map +1 -0
  120. package/lib/plugins/service-tunnels-admin/index.js +116 -0
  121. package/lib/plugins/service-tunnels-admin/index.js.map +1 -0
  122. package/lib/plugins/service-tunnels-client/ids.d.ts +6 -0
  123. package/lib/plugins/service-tunnels-client/ids.d.ts.map +1 -0
  124. package/lib/plugins/service-tunnels-client/ids.js +17 -0
  125. package/lib/plugins/service-tunnels-client/ids.js.map +1 -0
  126. package/lib/plugins/service-tunnels-client/index.d.ts +166 -0
  127. package/lib/plugins/service-tunnels-client/index.d.ts.map +1 -0
  128. package/lib/plugins/service-tunnels-client/index.js +733 -0
  129. package/lib/plugins/service-tunnels-client/index.js.map +1 -0
  130. package/lib/plugins/service-tunnels-client/registry.d.ts +39 -0
  131. package/lib/plugins/service-tunnels-client/registry.d.ts.map +1 -0
  132. package/lib/plugins/service-tunnels-client/registry.js +20 -0
  133. package/lib/plugins/service-tunnels-client/registry.js.map +1 -0
  134. package/lib/plugins/service-tunnels-client/schemas.d.ts +91 -0
  135. package/lib/plugins/service-tunnels-client/schemas.d.ts.map +1 -0
  136. package/lib/plugins/service-tunnels-client/schemas.js +73 -0
  137. package/lib/plugins/service-tunnels-client/schemas.js.map +1 -0
  138. package/lib/plugins/service-tunnels-proxy/http.d.ts +5 -0
  139. package/lib/plugins/service-tunnels-proxy/http.d.ts.map +1 -0
  140. package/lib/plugins/service-tunnels-proxy/http.js +125 -0
  141. package/lib/plugins/service-tunnels-proxy/http.js.map +1 -0
  142. package/lib/plugins/service-tunnels-proxy/index.d.ts +85 -0
  143. package/lib/plugins/service-tunnels-proxy/index.d.ts.map +1 -0
  144. package/lib/plugins/service-tunnels-proxy/index.js +288 -0
  145. package/lib/plugins/service-tunnels-proxy/index.js.map +1 -0
  146. package/lib/plugins/service-tunnels-proxy/verification.d.ts +31 -0
  147. package/lib/plugins/service-tunnels-proxy/verification.d.ts.map +1 -0
  148. package/lib/plugins/service-tunnels-proxy/verification.js +211 -0
  149. package/lib/plugins/service-tunnels-proxy/verification.js.map +1 -0
  150. package/lib/prisma.d.ts +7 -0
  151. package/lib/prisma.d.ts.map +1 -0
  152. package/lib/prisma.js +149 -0
  153. package/lib/prisma.js.map +1 -0
  154. package/lib/schemas/service-tunnels-admin.json +129 -0
  155. package/lib/schemas/service-tunnels-admin.plugin.json +140 -0
  156. package/lib/schemas/service-tunnels-client.json +320 -0
  157. package/lib/schemas/service-tunnels-client.plugin.json +97 -0
  158. package/lib/schemas/service-tunnels-proxy.json +160 -0
  159. package/lib/schemas/service-tunnels-proxy.plugin.json +123 -0
  160. package/package.json +1 -1
@@ -0,0 +1,57 @@
1
+ import * as av from "anyvali";
2
+ import { setTimeout as delay } from "node:timers/promises";
3
+ import { createStreamHandler } from "../../.bp-generated/route-runtime.js";
4
+ import { prisma } from "../../../../prisma.js";
5
+ const TunnelSchema = av.object({
6
+ id: av.string(),
7
+ subdomain: av.string(),
8
+ target: av.string(),
9
+ authenticated: av.bool(),
10
+ expiresAt: av.string(),
11
+ requests: av.number(),
12
+ bytesIn: av.number(),
13
+ bytesOut: av.number()
14
+ }, { unknownKeys: "strip" });
15
+ export const ItemSchema = av.object({
16
+ activeTunnels: av.number(),
17
+ requests: av.number(),
18
+ bytesIn: av.number(),
19
+ bytesOut: av.number(),
20
+ tunnels: av.array(TunnelSchema)
21
+ }, { unknownKeys: "strip" });
22
+ async function loadDashboard() {
23
+ const now = new Date();
24
+ const [tunnels, usageRows] = await Promise.all([
25
+ prisma.tunnel.findMany({
26
+ where: { status: "active", expiresAt: { gt: now } },
27
+ orderBy: { createdAt: "desc" },
28
+ include: { usage: true }
29
+ }),
30
+ prisma.usageCounter.findMany()
31
+ ]);
32
+ return {
33
+ activeTunnels: tunnels.length,
34
+ requests: usageRows.reduce((sum, row) => sum + row.requests, 0),
35
+ bytesIn: usageRows.reduce((sum, row) => sum + Number(row.bytesIn), 0),
36
+ bytesOut: usageRows.reduce((sum, row) => sum + Number(row.bytesOut), 0),
37
+ tunnels: tunnels.map((tunnel) => ({
38
+ id: tunnel.id,
39
+ subdomain: tunnel.subdomain,
40
+ target: `${tunnel.targetHost}:${tunnel.targetPort}`,
41
+ authenticated: tunnel.authenticated,
42
+ expiresAt: tunnel.expiresAt.toISOString(),
43
+ requests: tunnel.usage?.requests ?? 0,
44
+ bytesIn: Number(tunnel.usage?.bytesIn ?? 0n),
45
+ bytesOut: Number(tunnel.usage?.bytesOut ?? 0n)
46
+ }))
47
+ };
48
+ }
49
+ export default createStreamHandler({ item: ItemSchema }, async function* ({ headers }) {
50
+ const live = headers.accept?.includes("text/event-stream") ?? false;
51
+ do {
52
+ yield await loadDashboard();
53
+ if (live)
54
+ await delay(5_000);
55
+ } while (live);
56
+ });
57
+ //# sourceMappingURL=GET.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.js","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/dashboard/GET.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /** @jsxImportSource jsx-htmx */
2
+ import type { HtmlRenderable } from "@betterportal/framework";
3
+ import type { DashboardData, ResponseData } from "../GET.js";
4
+ export declare function renderDashboard(data: DashboardData): HtmlRenderable;
5
+ export declare function render(data: ResponseData): HtmlRenderable;
6
+ //# sourceMappingURL=GET.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.d.ts","sourceRoot":"","sources":["../../../../../../src/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/GET.tsx"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAS7D,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,cAAc,CA8DnE;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CAgBzD"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "jsx-htmx/jsx-runtime";
2
+ function formatBytes(value) {
3
+ if (value < 1024)
4
+ return `${value} B`;
5
+ if (value < 1024 * 1024)
6
+ return `${(value / 1024).toFixed(1)} KB`;
7
+ if (value < 1024 * 1024 * 1024)
8
+ return `${(value / 1024 / 1024).toFixed(1)} MB`;
9
+ return `${(value / 1024 / 1024 / 1024).toFixed(1)} GB`;
10
+ }
11
+ export function renderDashboard(data) {
12
+ const metrics = [
13
+ { label: "Active tunnels", value: String(data.activeTunnels) },
14
+ { label: "Requests handled", value: String(data.requests) },
15
+ { label: "Data received", value: formatBytes(data.bytesIn) },
16
+ { label: "Data sent", value: formatBytes(data.bytesOut) }
17
+ ];
18
+ return (_jsxs("section", { class: "container-fluid px-0", children: [_jsxs("div", { class: "d-flex justify-content-between align-items-center mb-3", children: [_jsx("p", { class: "text-body-secondary mb-0", children: "Live tunnel activity and traffic." }), _jsx("a", { class: "btn btn-outline-secondary btn-sm", href: "/tunnels", children: "History" })] }), _jsx("div", { class: "row g-3 mb-4", children: metrics.map((metric) => (_jsx("div", { class: "col-sm-6 col-xl-3", children: _jsxs("div", { class: "border rounded-3 p-3 bg-body h-100", children: [_jsx("div", { class: "small text-body-secondary mb-1", children: metric.label }), _jsx("div", { class: "h4 mb-0", children: metric.value })] }) }))) }), _jsxs("div", { class: "border rounded-3 bg-body", children: [_jsxs("div", { class: "d-flex justify-content-between align-items-center px-3 py-2 border-bottom", children: [_jsx("span", { class: "fw-semibold", children: "Active tunnels" }), _jsx("span", { class: "badge text-bg-success", children: "Live" })] }), _jsx("div", { class: "table-responsive", children: _jsxs("table", { class: "table table-sm table-hover align-middle mb-0", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Subdomain" }), _jsx("th", { children: "Target" }), _jsx("th", { children: "Mode" }), _jsx("th", { class: "text-end", children: "Requests" }), _jsx("th", { children: "Transfer" }), _jsx("th", { children: "Expires" })] }) }), _jsx("tbody", { children: data.tunnels.length === 0 ? (_jsx("tr", { children: _jsx("td", { colspan: "6", class: "text-center text-body-secondary py-4", children: "No active tunnels." }) })) : data.tunnels.map((tunnel) => (_jsxs("tr", { children: [_jsx("td", { children: _jsx("code", { children: tunnel.subdomain }) }), _jsx("td", { children: tunnel.target }), _jsx("td", { children: tunnel.authenticated ? "authenticated" : "anonymous" }), _jsx("td", { class: "text-end", children: String(tunnel.requests) }), _jsxs("td", { class: "small text-body-secondary", children: [formatBytes(tunnel.bytesIn), " in / ", formatBytes(tunnel.bytesOut), " out"] }), _jsx("td", { class: "small text-body-secondary", children: new Date(tunnel.expiresAt).toLocaleString() })] }))) })] }) })] })] }));
19
+ }
20
+ export function render(data) {
21
+ const dashboard = data.items[0] ?? {
22
+ activeTunnels: 0,
23
+ requests: 0,
24
+ bytesIn: 0,
25
+ bytesOut: 0,
26
+ tunnels: []
27
+ };
28
+ return (_jsx("div", { "hx-swap": "innerHTML", "hx-sse:connect": "/dashboard/__sse?_theme=bootstrap1", children: renderDashboard(dashboard) }));
29
+ }
30
+ //# sourceMappingURL=GET.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.js","sourceRoot":"","sources":["../../../../../../src/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/GET.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /** @jsxImportSource jsx-htmx */
2
+ import type { HtmlRenderable, StreamShellContext } from "@betterportal/framework";
3
+ import type { DashboardData } from "../GET.js";
4
+ export declare function renderShell({ sseConnectPath }: StreamShellContext): HtmlRenderable;
5
+ export declare function renderItem(data: DashboardData): HtmlRenderable;
6
+ //# sourceMappingURL=index.stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.stream.d.ts","sourceRoot":"","sources":["../../../../../../src/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/index.stream.tsx"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG/C,wBAAgB,WAAW,CAAC,EAAE,cAAc,EAAE,EAAE,kBAAkB,GAAG,cAAc,CAUlF;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,cAAc,CAE9D"}
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "jsx-htmx/jsx-runtime";
2
+ import { renderDashboard } from "./GET.js";
3
+ export function renderShell({ sseConnectPath }) {
4
+ return (_jsx("div", { class: "container-fluid px-0", "hx-swap": "innerHTML", "hx-sse:connect": sseConnectPath, children: _jsx("div", { class: "text-center text-body-secondary py-5", children: "Loading live tunnel data..." }) }));
5
+ }
6
+ export function renderItem(data) {
7
+ return renderDashboard(data);
8
+ }
9
+ //# sourceMappingURL=index.stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.stream.js","sourceRoot":"","sources":["../../../../../../src/plugins/service-tunnels-admin/bp-routes/dashboard/_theme.bootstrap1/index.stream.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,UAAU,WAAW,CAAC,EAAE,cAAc,EAAsB;IAChE,OAAO,CACL,cACE,KAAK,EAAC,sBAAsB,aACpB,WAAW,EACb,gBAAgB,EAAE,cAAc,YAEtC,cAAK,KAAK,EAAC,sCAAsC,4CAAkC,GAC/E,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAmB;IAC5C,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type ApiAuthRequirement, type CacheHints } from "@betterportal/framework";
2
+ export declare const viewId = "better-tunnels.dashboard";
3
+ export declare const title = "Tunnels";
4
+ export declare const description = "Live BetterTunnels activity.";
5
+ export declare const auth: ApiAuthRequirement;
6
+ export declare const cacheHints: CacheHints;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/dashboard/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,UAAU,EAChB,MAAM,yBAAyB,CAAC;AAEjC,eAAO,MAAM,MAAM,6BAA6B,CAAC;AACjD,eAAO,MAAM,KAAK,YAAY,CAAC;AAC/B,eAAO,MAAM,WAAW,iCAAiC,CAAC;AAE1D,eAAO,MAAM,IAAI,EAAE,kBAKlB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,UAGxB,CAAC"}
@@ -0,0 +1,14 @@
1
+ export const viewId = "better-tunnels.dashboard";
2
+ export const title = "Tunnels";
3
+ export const description = "Live BetterTunnels activity.";
4
+ export const auth = {
5
+ required: true,
6
+ permissions: [
7
+ { serviceId: "service.betterportal.tunnels", viewId, permissions: ["read"] }
8
+ ]
9
+ };
10
+ export const cacheHints = {
11
+ ttlSeconds: 0,
12
+ varyBy: ["accept", "authorization", "x-bp-tenant-id", "x-bp-app-id"]
13
+ };
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/dashboard/index.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,MAAM,GAAG,0BAA0B,CAAC;AACjD,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC;AAC/B,MAAM,CAAC,MAAM,WAAW,GAAG,8BAA8B,CAAC;AAE1D,MAAM,CAAC,MAAM,IAAI,GAAuB;IACtC,QAAQ,EAAE,IAAI;IACd,WAAW,EAAE;QACX,EAAE,SAAS,EAAE,8BAA8B,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE;KAC7E;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAe;IACpC,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,CAAC,QAAQ,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,CAAC;CACrE,CAAC"}
@@ -0,0 +1,25 @@
1
+ import * as av from "anyvali";
2
+ import type { Infer } from "anyvali";
3
+ export declare const ResponseSchema: av.ObjectSchema<{
4
+ latestTag: av.StringSchema;
5
+ logoUrl: av.StringSchema;
6
+ examples: av.ArraySchema<av.StringSchema>;
7
+ downloads: av.ArraySchema<av.ObjectSchema<{
8
+ os: av.StringSchema;
9
+ arch: av.StringSchema;
10
+ artifact: av.StringSchema;
11
+ }>>;
12
+ }>;
13
+ export type ResponseData = Infer<typeof ResponseSchema>;
14
+ declare const _default: import("@betterportal/framework").RouteHandler<Record<string, string>, Record<string, unknown>, Record<string, string>, Record<string, unknown>, {
15
+ latestTag: string;
16
+ logoUrl: string;
17
+ examples: string[];
18
+ downloads: {
19
+ os: string;
20
+ arch: string;
21
+ artifact: string;
22
+ }[];
23
+ }, unknown, Record<string, unknown>>;
24
+ export default _default;
25
+ //# sourceMappingURL=GET.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/downloads/GET.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAUrC,eAAO,MAAM,cAAc;;;;;;;;;EAKC,CAAC;AAC7B,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;;;;;;;;;;;AAExD,wBAsBE"}
@@ -0,0 +1,34 @@
1
+ import * as av from "anyvali";
2
+ import { createHandler } from "@betterportal/framework";
3
+ import { loadBrandAssets } from "../../brand-assets.js";
4
+ const DownloadSchema = av.object({
5
+ os: av.string(),
6
+ arch: av.string(),
7
+ artifact: av.string()
8
+ }, { unknownKeys: "strip" });
9
+ export const ResponseSchema = av.object({
10
+ latestTag: av.string(),
11
+ logoUrl: av.string(),
12
+ examples: av.array(av.string()),
13
+ downloads: av.array(DownloadSchema)
14
+ }, { unknownKeys: "strip" });
15
+ export default createHandler({ response: ResponseSchema }, async () => {
16
+ const brand = await loadBrandAssets();
17
+ return {
18
+ latestTag: "v0.1.0",
19
+ logoUrl: brand.logoUrl,
20
+ examples: [
21
+ "better-tunnels tunnel --port 3100",
22
+ "better-tunnels tunnel --host 127.0.0.1 --port 3100",
23
+ "better-tunnels tunnel --config .bettertunnel"
24
+ ],
25
+ downloads: [
26
+ { os: "Windows", arch: "amd64", artifact: "better-tunnels-windows-amd64.exe" },
27
+ { os: "Linux", arch: "amd64", artifact: "better-tunnels-linux-amd64" },
28
+ { os: "Linux", arch: "arm64", artifact: "better-tunnels-linux-arm64" },
29
+ { os: "macOS", arch: "amd64", artifact: "better-tunnels-darwin-amd64" },
30
+ { os: "macOS", arch: "arm64", artifact: "better-tunnels-darwin-arm64" }
31
+ ]
32
+ };
33
+ });
34
+ //# sourceMappingURL=GET.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.js","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/downloads/GET.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,cAAc,GAAG,EAAE,CAAC,MAAM,CAAC;IAC/B,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE;IACf,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE;IACjB,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE;CACtB,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;AAE7B,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC,MAAM,CAAC;IACtC,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE;IACtB,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;IAC/B,SAAS,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC;CACpC,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;AAG7B,eAAe,aAAa,CAC1B,EAAE,QAAQ,EAAE,cAAc,EAAE,EAC5B,KAAK,IAAI,EAAE;IACT,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IAEtC,OAAO;QACL,SAAS,EAAE,QAAQ;QACnB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE;YACR,mCAAmC;YACnC,oDAAoD;YACpD,8CAA8C;SAC/C;QACD,SAAS,EAAE;YACT,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,kCAAkC,EAAE;YAC9E,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,4BAA4B,EAAE;YACtE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,4BAA4B,EAAE;YACtE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,6BAA6B,EAAE;YACvE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,6BAA6B,EAAE;SACxE;KACF,CAAC;AACJ,CAAC,CACF,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** @jsxImportSource jsx-htmx */
2
+ import type { HtmlRenderable } from "@betterportal/framework";
3
+ import type { ResponseData } from "../GET.js";
4
+ export declare function render(data: ResponseData): HtmlRenderable;
5
+ //# sourceMappingURL=GET.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.d.ts","sourceRoot":"","sources":["../../../../../../src/plugins/service-tunnels-admin/bp-routes/downloads/_theme.bootstrap1/GET.tsx"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,wBAAgB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CAsDzD"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "jsx-htmx/jsx-runtime";
2
+ export function render(data) {
3
+ return (_jsxs("section", { class: "container-fluid px-0", children: [_jsxs("div", { class: "mb-4", children: [_jsx("img", { src: data.logoUrl, alt: "BetterTunnels", class: "img-fluid mb-3", style: "max-width: 280px; height: auto;" }), _jsx("h1", { class: "h3 mb-1", children: "BetterTunnels CLI" }), _jsx("p", { class: "text-body-secondary mb-0", children: "Download the CLI and start a public development tunnel." })] }), _jsxs("div", { class: "row g-4", children: [_jsx("div", { class: "col-lg-5", children: _jsxs("div", { class: "border rounded-3 p-4 bg-body h-100", children: [_jsx("h2", { class: "h5 mb-3", children: "Quick start" }), data.examples.map((example) => (_jsx("pre", { class: "small bg-body-tertiary border rounded-2 p-3 mb-2", children: _jsx("code", { children: example }) })))] }) }), _jsx("div", { class: "col-lg-7", children: _jsxs("div", { class: "border rounded-3 bg-body h-100", children: [_jsxs("div", { class: "px-3 py-2 border-bottom d-flex justify-content-between", children: [_jsx("span", { class: "fw-semibold", children: "Release assets" }), _jsx("span", { class: "text-body-secondary", children: data.latestTag })] }), _jsx("div", { class: "table-responsive", children: _jsxs("table", { class: "table table-sm align-middle mb-0", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "OS" }), _jsx("th", { children: "Arch" }), _jsx("th", { children: "Artifact" })] }) }), _jsx("tbody", { children: data.downloads.map((download) => (_jsxs("tr", { children: [_jsx("td", { children: download.os }), _jsx("td", { children: download.arch }), _jsx("td", { children: _jsx("code", { children: download.artifact }) })] }))) })] }) })] }) })] })] }));
4
+ }
5
+ //# sourceMappingURL=GET.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.js","sourceRoot":"","sources":["../../../../../../src/plugins/service-tunnels-admin/bp-routes/downloads/_theme.bootstrap1/GET.tsx"],"names":[],"mappings":";AAIA,MAAM,UAAU,MAAM,CAAC,IAAkB;IACvC,OAAO,CACL,mBAAS,KAAK,EAAC,sBAAsB,aACnC,eAAK,KAAK,EAAC,MAAM,aACf,cACE,GAAG,EAAE,IAAI,CAAC,OAAO,EACjB,GAAG,EAAC,eAAe,EACnB,KAAK,EAAC,gBAAgB,EACtB,KAAK,EAAC,iCAAiC,GACvC,EACF,aAAI,KAAK,EAAC,SAAS,kCAAuB,EAC1C,YAAG,KAAK,EAAC,0BAA0B,wEAA4D,IAC3F,EAEN,eAAK,KAAK,EAAC,SAAS,aAClB,cAAK,KAAK,EAAC,UAAU,YACnB,eAAK,KAAK,EAAC,oCAAoC,aAC7C,aAAI,KAAK,EAAC,SAAS,4BAAiB,EACnC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAC9B,cAAK,KAAK,EAAC,kDAAkD,YAAC,yBAAO,OAAO,GAAQ,GAAM,CAC3F,CAAC,IACE,GACF,EACN,cAAK,KAAK,EAAC,UAAU,YACnB,eAAK,KAAK,EAAC,gCAAgC,aACzC,eAAK,KAAK,EAAC,wDAAwD,aACjE,eAAM,KAAK,EAAC,aAAa,+BAAsB,EAC/C,eAAM,KAAK,EAAC,qBAAqB,YAAE,IAAI,CAAC,SAAS,GAAQ,IACrD,EACN,cAAK,KAAK,EAAC,kBAAkB,YAC3B,iBAAO,KAAK,EAAC,kCAAkC,aAC7C,0BACE,yBACE,8BAAW,EACX,gCAAa,EACb,oCAAiB,IACd,GACC,EACR,0BACG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAChC,yBACE,uBAAK,QAAQ,CAAC,EAAE,GAAM,EACtB,uBAAK,QAAQ,CAAC,IAAI,GAAM,EACxB,uBAAI,yBAAO,QAAQ,CAAC,QAAQ,GAAQ,GAAK,IACtC,CACN,CAAC,GACI,IACF,GACJ,IACF,GACF,IACF,IACE,CACX,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type ApiAuthRequirement, type CacheHints } from "@betterportal/framework";
2
+ export declare const viewId = "better-tunnels.downloads";
3
+ export declare const title = "BetterTunnels CLI";
4
+ export declare const description = "CLI download and setup commands.";
5
+ export declare const auth: ApiAuthRequirement;
6
+ export declare const cacheHints: CacheHints;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/downloads/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,UAAU,EAChB,MAAM,yBAAyB,CAAC;AAEjC,eAAO,MAAM,MAAM,6BAA6B,CAAC;AACjD,eAAO,MAAM,KAAK,sBAAsB,CAAC;AACzC,eAAO,MAAM,WAAW,qCAAqC,CAAC;AAE9D,eAAO,MAAM,IAAI,EAAE,kBAGlB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,UAGxB,CAAC"}
@@ -0,0 +1,12 @@
1
+ export const viewId = "better-tunnels.downloads";
2
+ export const title = "BetterTunnels CLI";
3
+ export const description = "CLI download and setup commands.";
4
+ export const auth = {
5
+ required: false,
6
+ permissions: []
7
+ };
8
+ export const cacheHints = {
9
+ ttlSeconds: 60,
10
+ varyBy: ["accept", "x-bp-tenant-id", "x-bp-app-id"]
11
+ };
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/downloads/index.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,MAAM,GAAG,0BAA0B,CAAC;AACjD,MAAM,CAAC,MAAM,KAAK,GAAG,mBAAmB,CAAC;AACzC,MAAM,CAAC,MAAM,WAAW,GAAG,kCAAkC,CAAC;AAE9D,MAAM,CAAC,MAAM,IAAI,GAAuB;IACtC,QAAQ,EAAE,KAAK;IACf,WAAW,EAAE,EAAE;CAChB,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAe;IACpC,UAAU,EAAE,EAAE;IACd,MAAM,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,aAAa,CAAC;CACpD,CAAC"}
@@ -0,0 +1,35 @@
1
+ import * as av from "anyvali";
2
+ import type { Infer } from "anyvali";
3
+ export declare const ResponseSchema: av.ObjectSchema<{
4
+ product: av.StringSchema;
5
+ domain: av.StringSchema;
6
+ connectHost: av.StringSchema;
7
+ webHost: av.StringSchema;
8
+ logoUrl: av.StringSchema;
9
+ markUrl: av.StringSchema;
10
+ faviconUrl: av.StringSchema;
11
+ cliInstall: av.ArraySchema<av.StringSchema>;
12
+ highlights: av.ArraySchema<av.ObjectSchema<{
13
+ title: av.StringSchema;
14
+ body: av.StringSchema;
15
+ }>>;
16
+ limits: av.ArraySchema<av.StringSchema>;
17
+ }>;
18
+ export type ResponseData = Infer<typeof ResponseSchema>;
19
+ declare const _default: import("@betterportal/framework").RouteHandler<Record<string, string>, Record<string, unknown>, Record<string, string>, Record<string, unknown>, {
20
+ product: string;
21
+ domain: string;
22
+ connectHost: string;
23
+ webHost: string;
24
+ logoUrl: string;
25
+ markUrl: string;
26
+ faviconUrl: string;
27
+ cliInstall: string[];
28
+ highlights: {
29
+ title: string;
30
+ body: string;
31
+ }[];
32
+ limits: string[];
33
+ }, unknown, Record<string, unknown>>;
34
+ export default _default;
35
+ //# sourceMappingURL=GET.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/landing/GET.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAIrC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;EAcC,CAAC;AAC7B,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;;;;;;;;;;;;;;;;AAExD,wBAoCE"}
@@ -0,0 +1,52 @@
1
+ import * as av from "anyvali";
2
+ import { createHandler } from "@betterportal/framework";
3
+ import { loadBrandAssets } from "../../brand-assets.js";
4
+ export const ResponseSchema = av.object({
5
+ product: av.string(),
6
+ domain: av.string(),
7
+ connectHost: av.string(),
8
+ webHost: av.string(),
9
+ logoUrl: av.string(),
10
+ markUrl: av.string(),
11
+ faviconUrl: av.string(),
12
+ cliInstall: av.array(av.string()),
13
+ highlights: av.array(av.object({
14
+ title: av.string(),
15
+ body: av.string()
16
+ }, { unknownKeys: "strip" })),
17
+ limits: av.array(av.string())
18
+ }, { unknownKeys: "strip" });
19
+ export default createHandler({ response: ResponseSchema }, async () => {
20
+ const brand = await loadBrandAssets();
21
+ return {
22
+ product: "BetterTunnels",
23
+ domain: "tunnels.betterportal.dev",
24
+ connectHost: "connect.tunnels.betterportal.dev",
25
+ webHost: "betterportal.tunnels.betterportal.dev",
26
+ ...brand,
27
+ cliInstall: [
28
+ "better-tunnels tunnel --port 3100",
29
+ "better-tunnels tunnel --config .bettertunnel"
30
+ ],
31
+ highlights: [
32
+ {
33
+ title: "HTTP and HTTPS tunnels",
34
+ body: "Expose local development servers through generated, short-lived public URLs."
35
+ },
36
+ {
37
+ title: "Verification-first access",
38
+ body: "Visitors pass through a clear development-tunnel warning before reaching a tunnel."
39
+ },
40
+ {
41
+ title: "Built for operations",
42
+ body: "Structured request timings, trace-friendly sessions, and BetterPortal management routes."
43
+ }
44
+ ],
45
+ limits: [
46
+ "Anonymous sessions are temporary.",
47
+ "Tunnel subdomains are generated by the platform.",
48
+ "Registered accounts can unlock higher limits and verification controls later."
49
+ ]
50
+ };
51
+ });
52
+ //# sourceMappingURL=GET.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.js","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/landing/GET.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC,MAAM,CAAC;IACtC,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE;IACpB,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE;IACnB,WAAW,EAAE,EAAE,CAAC,MAAM,EAAE;IACxB,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE;IACpB,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE;IACpB,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE;IACpB,UAAU,EAAE,EAAE,CAAC,MAAM,EAAE;IACvB,UAAU,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;IACjC,UAAU,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC;QAC7B,KAAK,EAAE,EAAE,CAAC,MAAM,EAAE;QAClB,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE;KAClB,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;IAC7B,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;CAC9B,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;AAG7B,eAAe,aAAa,CAC1B,EAAE,QAAQ,EAAE,cAAc,EAAE,EAC5B,KAAK,IAAI,EAAE;IACT,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IAEtC,OAAO;QACL,OAAO,EAAE,eAAe;QACxB,MAAM,EAAE,0BAA0B;QAClC,WAAW,EAAE,kCAAkC;QAC/C,OAAO,EAAE,uCAAuC;QAChD,GAAG,KAAK;QACR,UAAU,EAAE;YACV,mCAAmC;YACnC,8CAA8C;SAC/C;QACD,UAAU,EAAE;YACV;gBACE,KAAK,EAAE,wBAAwB;gBAC/B,IAAI,EAAE,8EAA8E;aACrF;YACD;gBACE,KAAK,EAAE,2BAA2B;gBAClC,IAAI,EAAE,oFAAoF;aAC3F;YACD;gBACE,KAAK,EAAE,sBAAsB;gBAC7B,IAAI,EAAE,0FAA0F;aACjG;SACF;QACD,MAAM,EAAE;YACN,mCAAmC;YACnC,kDAAkD;YAClD,+EAA+E;SAChF;KACF,CAAC;AACJ,CAAC,CACF,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** @jsxImportSource jsx-htmx */
2
+ import type { HtmlRenderable } from "@betterportal/framework";
3
+ import type { ResponseData } from "../GET.js";
4
+ export declare function render(data: ResponseData): HtmlRenderable;
5
+ //# sourceMappingURL=GET.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.d.ts","sourceRoot":"","sources":["../../../../../../src/plugins/service-tunnels-admin/bp-routes/landing/_theme.bootstrap1/GET.tsx"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,wBAAgB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CA2FzD"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "jsx-htmx/jsx-runtime";
2
+ export function render(data) {
3
+ return (_jsxs("main", { class: "container-fluid px-0", children: [_jsx("section", { class: "py-5", children: _jsxs("div", { class: "row align-items-center g-5", children: [_jsxs("div", { class: "col-lg-7", children: [_jsx("img", { src: data.logoUrl, alt: "BetterTunnels", class: "img-fluid mb-4", style: "max-width: 360px; height: auto;" }), _jsx("div", { class: "mb-3 text-uppercase fw-semibold text-danger small", children: data.domain }), _jsx("h1", { class: "display-4 fw-semibold mb-3", children: "Public dev tunnels with a verification gate" }), _jsx("p", { class: "lead text-body-secondary mb-4", children: "Public development tunnels with explicit visitor verification, operator visibility, and a CLI workflow designed for local projects." }), _jsxs("div", { class: "d-flex flex-wrap gap-2", children: [_jsx("a", { class: "btn btn-danger btn-lg", href: "/downloads", children: "Get the CLI" }), _jsx("a", { class: "btn btn-outline-secondary btn-lg", href: "/dashboard", children: "Open dashboard" })] })] }), _jsx("div", { class: "col-lg-5", children: _jsxs("div", { class: "border rounded-3 bg-body-tertiary p-3 shadow-sm", children: [_jsxs("div", { class: "d-flex align-items-center justify-content-between border-bottom pb-2 mb-3", children: [_jsxs("span", { class: "d-flex align-items-center gap-2 fw-semibold", children: [_jsx("img", { src: data.faviconUrl, alt: "", width: "24", height: "24" }), "local project"] }), _jsx("span", { class: "badge text-bg-danger", children: "public" })] }), _jsx("div", { class: "text-center py-3", children: _jsx("img", { src: data.markUrl, alt: "", class: "img-fluid rounded-3", style: "max-width: 180px;" }) }), _jsx("pre", { class: "mb-3 small", children: _jsx("code", { children: data.cliInstall[0] }) }), _jsxs("div", { class: "bg-body border rounded-2 p-3 small", children: [_jsx("div", { class: "text-body-secondary mb-1", children: "Tunnel URL" }), _jsxs("code", { children: ["https://a1b2c3-port3100-203-0-113-10.", data.domain] })] }), _jsxs("div", { class: "row g-2 mt-2 small", children: [_jsx("div", { class: "col-4", children: _jsx("div", { class: "border rounded-2 p-2 bg-body", children: "verify" }) }), _jsx("div", { class: "col-4", children: _jsx("div", { class: "border rounded-2 p-2 bg-body", children: "proxy" }) }), _jsx("div", { class: "col-4", children: _jsx("div", { class: "border rounded-2 p-2 bg-body", children: "trace" }) })] })] }) })] }) }), _jsx("section", { class: "py-4 border-top", children: _jsx("div", { class: "row g-3", children: data.highlights.map((item) => (_jsx("div", { class: "col-md-4", children: _jsxs("div", { class: "h-100 border rounded-3 p-4 bg-body", children: [_jsx("h2", { class: "h5 mb-2", children: item.title }), _jsx("p", { class: "text-body-secondary mb-0", children: item.body })] }) }))) }) }), _jsx("section", { class: "py-4 border-top", children: _jsxs("div", { class: "row g-4 align-items-start", children: [_jsxs("div", { class: "col-lg-5", children: [_jsx("h2", { class: "h4 mb-2", children: "Managed by BetterPortal" }), _jsx("p", { class: "text-body-secondary mb-0", children: "The public site, dashboard, and future account controls run as BetterPortal routes. Tunnel traffic can stay on separate infrastructure while this service manages the UI." })] }), _jsx("div", { class: "col-lg-7", children: _jsx("ul", { class: "list-group list-group-flush border rounded-3", children: data.limits.map((limit) => (_jsxs("li", { class: "list-group-item d-flex gap-2 align-items-start", children: [_jsx("span", { class: "text-danger fw-bold", children: "!" }), _jsx("span", { children: limit })] }))) }) })] }) })] }));
4
+ }
5
+ //# sourceMappingURL=GET.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.js","sourceRoot":"","sources":["../../../../../../src/plugins/service-tunnels-admin/bp-routes/landing/_theme.bootstrap1/GET.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { type ApiAuthRequirement, type CacheHints } from "@betterportal/framework";
2
+ export declare const viewId = "better-tunnels.landing";
3
+ export declare const title = "BetterTunnels";
4
+ export declare const description = "Public landing page for BetterTunnels.";
5
+ export declare const auth: ApiAuthRequirement;
6
+ export declare const cacheHints: CacheHints;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/landing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,UAAU,EAChB,MAAM,yBAAyB,CAAC;AAEjC,eAAO,MAAM,MAAM,2BAA2B,CAAC;AAC/C,eAAO,MAAM,KAAK,kBAAkB,CAAC;AACrC,eAAO,MAAM,WAAW,2CAA2C,CAAC;AAEpE,eAAO,MAAM,IAAI,EAAE,kBAGlB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,UAGxB,CAAC"}
@@ -0,0 +1,12 @@
1
+ export const viewId = "better-tunnels.landing";
2
+ export const title = "BetterTunnels";
3
+ export const description = "Public landing page for BetterTunnels.";
4
+ export const auth = {
5
+ required: false,
6
+ permissions: []
7
+ };
8
+ export const cacheHints = {
9
+ ttlSeconds: 60,
10
+ varyBy: ["accept", "x-bp-tenant-id", "x-bp-app-id"]
11
+ };
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/landing/index.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,MAAM,GAAG,wBAAwB,CAAC;AAC/C,MAAM,CAAC,MAAM,KAAK,GAAG,eAAe,CAAC;AACrC,MAAM,CAAC,MAAM,WAAW,GAAG,wCAAwC,CAAC;AAEpE,MAAM,CAAC,MAAM,IAAI,GAAuB;IACtC,QAAQ,EAAE,KAAK;IACf,WAAW,EAAE,EAAE;CAChB,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAe;IACpC,UAAU,EAAE,EAAE;IACd,MAAM,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,aAAa,CAAC;CACpD,CAAC"}
@@ -0,0 +1,39 @@
1
+ import * as av from "anyvali";
2
+ import type { Infer } from "anyvali";
3
+ export declare const ResponseSchema: av.ObjectSchema<{
4
+ active: av.NumberSchema;
5
+ total: av.NumberSchema;
6
+ tunnels: av.ArraySchema<av.ObjectSchema<{
7
+ id: av.StringSchema;
8
+ subdomain: av.StringSchema;
9
+ target: av.StringSchema;
10
+ authenticated: av.BoolSchema;
11
+ status: av.StringSchema;
12
+ ownerServerId: av.OptionalSchema<av.StringSchema>;
13
+ createdAt: av.StringSchema;
14
+ expiresAt: av.StringSchema;
15
+ requests: av.NumberSchema;
16
+ bytesIn: av.NumberSchema;
17
+ bytesOut: av.NumberSchema;
18
+ }>>;
19
+ }>;
20
+ export type ResponseData = Infer<typeof ResponseSchema>;
21
+ declare const _default: import("@betterportal/framework").RouteHandler<Record<string, string>, Record<string, unknown>, Record<string, string>, Record<string, unknown>, {
22
+ active: number;
23
+ total: number;
24
+ tunnels: {
25
+ id: string;
26
+ subdomain: string;
27
+ target: string;
28
+ authenticated: boolean;
29
+ status: string;
30
+ createdAt: string;
31
+ expiresAt: string;
32
+ requests: number;
33
+ bytesIn: number;
34
+ bytesOut: number;
35
+ ownerServerId?: string | undefined;
36
+ }[];
37
+ }, unknown, Record<string, unknown>>;
38
+ export default _default;
39
+ //# sourceMappingURL=GET.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/tunnels/GET.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAkBrC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;EAIC,CAAC;AAC7B,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;;;;;;;;;;;;;;;;;;AAExD,wBA2BE"}
@@ -0,0 +1,46 @@
1
+ import * as av from "anyvali";
2
+ import { createHandler } from "@betterportal/framework";
3
+ import { prisma } from "../../../../prisma.js";
4
+ const TunnelRowSchema = av.object({
5
+ id: av.string(),
6
+ subdomain: av.string(),
7
+ target: av.string(),
8
+ authenticated: av.bool(),
9
+ status: av.string(),
10
+ ownerServerId: av.optional(av.string()),
11
+ createdAt: av.string(),
12
+ expiresAt: av.string(),
13
+ requests: av.number(),
14
+ bytesIn: av.number(),
15
+ bytesOut: av.number()
16
+ }, { unknownKeys: "strip" });
17
+ export const ResponseSchema = av.object({
18
+ active: av.number(),
19
+ total: av.number(),
20
+ tunnels: av.array(TunnelRowSchema)
21
+ }, { unknownKeys: "strip" });
22
+ export default createHandler({ response: ResponseSchema }, async () => {
23
+ const rows = await prisma.tunnel.findMany({
24
+ orderBy: { createdAt: "desc" },
25
+ take: 50,
26
+ include: { usage: true }
27
+ });
28
+ return {
29
+ active: rows.filter((row) => row.status === "active").length,
30
+ total: rows.length,
31
+ tunnels: rows.map((row) => ({
32
+ id: row.id,
33
+ subdomain: row.subdomain,
34
+ target: `${row.targetHost}:${row.targetPort}`,
35
+ authenticated: row.authenticated,
36
+ status: row.status,
37
+ ownerServerId: row.ownerServerId ?? undefined,
38
+ createdAt: row.createdAt.toISOString(),
39
+ expiresAt: row.expiresAt.toISOString(),
40
+ requests: row.usage?.requests ?? 0,
41
+ bytesIn: Number(row.usage?.bytesIn ?? 0n),
42
+ bytesOut: Number(row.usage?.bytesOut ?? 0n)
43
+ }))
44
+ };
45
+ });
46
+ //# sourceMappingURL=GET.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.js","sourceRoot":"","sources":["../../../../../src/plugins/service-tunnels-admin/bp-routes/tunnels/GET.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,MAAM,eAAe,GAAG,EAAE,CAAC,MAAM,CAAC;IAChC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE;IACf,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE;IACtB,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE;IACnB,aAAa,EAAE,EAAE,CAAC,IAAI,EAAE;IACxB,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE;IACnB,aAAa,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;IACvC,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE;IACtB,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE;IACtB,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE;IACrB,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE;CACtB,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;AAE7B,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC,MAAM,CAAC;IACtC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE;IACnB,KAAK,EAAE,EAAE,CAAC,MAAM,EAAE;IAClB,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC;CACnC,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;AAG7B,eAAe,aAAa,CAC1B,EAAE,QAAQ,EAAE,cAAc,EAAE,EAC5B,KAAK,IAAI,EAAE;IACT,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;QACxC,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;QAC9B,IAAI,EAAE,EAAE;QACR,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;KACzB,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM;QAC5D,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC1B,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,EAAE;YAC7C,aAAa,EAAE,GAAG,CAAC,aAAa;YAChC,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,aAAa,EAAE,GAAG,CAAC,aAAa,IAAI,SAAS;YAC7C,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE;YACtC,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE;YACtC,QAAQ,EAAE,GAAG,CAAC,KAAK,EAAE,QAAQ,IAAI,CAAC;YAClC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC;YACzC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,IAAI,EAAE,CAAC;SAC5C,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC,CACF,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** @jsxImportSource jsx-htmx */
2
+ import type { HtmlRenderable } from "@betterportal/framework";
3
+ import type { ResponseData } from "../GET.js";
4
+ export declare function render(data: ResponseData): HtmlRenderable;
5
+ //# sourceMappingURL=GET.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.d.ts","sourceRoot":"","sources":["../../../../../../src/plugins/service-tunnels-admin/bp-routes/tunnels/_theme.bootstrap1/GET.tsx"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,wBAAgB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CAmDzD"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "jsx-htmx/jsx-runtime";
2
+ export function render(data) {
3
+ return (_jsxs("section", { class: "container-fluid px-0", children: [_jsxs("div", { class: "d-flex justify-content-between align-items-start mb-4", children: [_jsxs("div", { children: [_jsx("h1", { class: "h3 mb-1", children: "BetterTunnels" }), _jsx("p", { class: "text-body-secondary mb-0", children: "Live tunnel sessions and recent usage." })] }), _jsxs("div", { class: "text-end", children: [_jsx("div", { class: "h4 mb-0", children: String(data.active) }), _jsxs("div", { class: "small text-body-secondary", children: ["active / ", String(data.total), " shown"] })] })] }), _jsx("div", { class: "card border-0 shadow-sm", children: _jsx("div", { class: "table-responsive", children: _jsxs("table", { class: "table table-sm table-hover align-middle mb-0", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Subdomain" }), _jsx("th", { children: "Target" }), _jsx("th", { children: "Status" }), _jsx("th", { children: "Mode" }), _jsx("th", { class: "text-end", children: "Requests" }), _jsx("th", { children: "Expires" })] }) }), _jsx("tbody", { children: data.tunnels.length === 0 ? (_jsx("tr", { children: _jsx("td", { colspan: "6", class: "text-center text-body-secondary py-4", children: "No tunnels yet." }) })) : data.tunnels.map((tunnel) => (_jsxs("tr", { children: [_jsxs("td", { children: [_jsx("code", { children: tunnel.subdomain }), _jsx("div", { class: "small text-body-secondary", children: tunnel.ownerServerId ?? "no owner" })] }), _jsx("td", { children: tunnel.target }), _jsx("td", { children: _jsx("span", { class: `badge ${tunnel.status === "active" ? "text-bg-success" : "text-bg-secondary"}`, children: tunnel.status }) }), _jsx("td", { children: tunnel.authenticated ? "authenticated" : "anonymous" }), _jsx("td", { class: "text-end", children: String(tunnel.requests) }), _jsx("td", { class: "small text-body-secondary", children: new Date(tunnel.expiresAt).toLocaleString() })] }))) })] }) }) })] }));
4
+ }
5
+ //# sourceMappingURL=GET.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GET.js","sourceRoot":"","sources":["../../../../../../src/plugins/service-tunnels-admin/bp-routes/tunnels/_theme.bootstrap1/GET.tsx"],"names":[],"mappings":";AAIA,MAAM,UAAU,MAAM,CAAC,IAAkB;IACvC,OAAO,CACL,mBAAS,KAAK,EAAC,sBAAsB,aACnC,eAAK,KAAK,EAAC,uDAAuD,aAChE,0BACE,aAAI,KAAK,EAAC,SAAS,8BAAmB,EACtC,YAAG,KAAK,EAAC,0BAA0B,uDAA2C,IAC1E,EACN,eAAK,KAAK,EAAC,UAAU,aACnB,cAAK,KAAK,EAAC,SAAS,YAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAO,EAChD,eAAK,KAAK,EAAC,2BAA2B,0BAAW,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,cAAa,IAC5E,IACF,EAEN,cAAK,KAAK,EAAC,yBAAyB,YAClC,cAAK,KAAK,EAAC,kBAAkB,YAC3B,iBAAO,KAAK,EAAC,8CAA8C,aACzD,0BACE,yBACE,qCAAkB,EAClB,kCAAe,EACf,kCAAe,EACf,gCAAa,EACb,aAAI,KAAK,EAAC,UAAU,yBAAc,EAClC,mCAAgB,IACb,GACC,EACR,0BACG,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAC3B,uBACE,aAAI,OAAO,EAAC,GAAG,EAAC,KAAK,EAAC,sCAAsC,gCAAqB,GAC9E,CACN,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAC/B,yBACE,yBACE,yBAAO,MAAM,CAAC,SAAS,GAAQ,EAC/B,cAAK,KAAK,EAAC,2BAA2B,YAAE,MAAM,CAAC,aAAa,IAAI,UAAU,GAAO,IAC9E,EACL,uBAAK,MAAM,CAAC,MAAM,GAAM,EACxB,uBAAI,eAAM,KAAK,EAAE,SAAS,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,mBAAmB,EAAE,YAAG,MAAM,CAAC,MAAM,GAAQ,GAAK,EAC7H,uBAAK,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,GAAM,EAC/D,aAAI,KAAK,EAAC,UAAU,YAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAM,EACnD,aAAI,KAAK,EAAC,2BAA2B,YAAE,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,GAAM,IACrF,CACN,CAAC,GACI,IACF,GACJ,GACF,IACE,CACX,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type ApiAuthRequirement, type CacheHints } from "@betterportal/framework";
2
+ export declare const viewId = "better-tunnels.tunnels";
3
+ export declare const title = "BetterTunnels";
4
+ export declare const description = "Tunnel sessions, status, and recent activity.";
5
+ export declare const auth: ApiAuthRequirement;
6
+ export declare const cacheHints: CacheHints;
7
+ //# sourceMappingURL=index.d.ts.map