@replicated/portal-components 0.0.18 → 0.0.20

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 (250) hide show
  1. package/components/metadata/registry.json +2 -2
  2. package/components/metadata/registry.md +2 -2
  3. package/dist/actions/change-team.d.mts +10 -0
  4. package/dist/actions/change-team.d.ts +10 -0
  5. package/dist/actions/change-team.js +458 -0
  6. package/dist/actions/change-team.js.map +1 -0
  7. package/dist/actions/index.d.mts +4 -1
  8. package/dist/actions/index.d.ts +4 -1
  9. package/dist/actions/index.js +1232 -430
  10. package/dist/actions/index.js.map +1 -1
  11. package/dist/actions/install-actions.d.mts +4 -0
  12. package/dist/actions/install-actions.d.ts +4 -0
  13. package/dist/actions/install-actions.js +680 -0
  14. package/dist/actions/install-actions.js.map +1 -0
  15. package/dist/actions/service-account.d.mts +4 -0
  16. package/dist/actions/service-account.d.ts +4 -0
  17. package/dist/actions/service-account.js +373 -0
  18. package/dist/actions/service-account.js.map +1 -0
  19. package/dist/actions/support-bundles.d.mts +4 -0
  20. package/dist/actions/support-bundles.d.ts +4 -0
  21. package/dist/actions/support-bundles.js +659 -0
  22. package/dist/actions/support-bundles.js.map +1 -0
  23. package/dist/actions/team-settings.d.mts +4 -0
  24. package/dist/actions/team-settings.d.ts +4 -0
  25. package/dist/actions/team-settings.js +1040 -0
  26. package/dist/actions/team-settings.js.map +1 -0
  27. package/dist/actions/trial-signup.d.mts +24 -0
  28. package/dist/actions/trial-signup.d.ts +24 -0
  29. package/dist/actions/trial-signup.js +482 -0
  30. package/dist/actions/trial-signup.js.map +1 -0
  31. package/dist/actions/user-settings.d.mts +4 -0
  32. package/dist/actions/user-settings.d.ts +4 -0
  33. package/dist/actions/user-settings.js +621 -0
  34. package/dist/actions/user-settings.js.map +1 -0
  35. package/dist/airgap-instances.d.mts +4 -1
  36. package/dist/airgap-instances.d.ts +4 -1
  37. package/dist/airgap-instances.js +177 -32
  38. package/dist/airgap-instances.js.map +1 -1
  39. package/dist/branding-BsMSywts.d.mts +36 -0
  40. package/dist/branding-BsMSywts.d.ts +36 -0
  41. package/dist/error-page.js +10 -2
  42. package/dist/error-page.js.map +1 -1
  43. package/dist/error.js +10 -2
  44. package/dist/error.js.map +1 -1
  45. package/dist/esm/actions/change-team.js +455 -0
  46. package/dist/esm/actions/change-team.js.map +1 -0
  47. package/dist/esm/actions/index.js +1200 -428
  48. package/dist/esm/actions/index.js.map +1 -1
  49. package/dist/esm/actions/install-actions.js +673 -0
  50. package/dist/esm/actions/install-actions.js.map +1 -0
  51. package/dist/esm/actions/service-account.js +371 -0
  52. package/dist/esm/actions/service-account.js.map +1 -0
  53. package/dist/esm/actions/support-bundles.js +654 -0
  54. package/dist/esm/actions/support-bundles.js.map +1 -0
  55. package/dist/esm/actions/team-settings.js +1026 -0
  56. package/dist/esm/actions/team-settings.js.map +1 -0
  57. package/dist/esm/actions/trial-signup.js +478 -0
  58. package/dist/esm/actions/trial-signup.js.map +1 -0
  59. package/dist/esm/actions/user-settings.js +615 -0
  60. package/dist/esm/actions/user-settings.js.map +1 -0
  61. package/dist/esm/airgap-instances.js +176 -32
  62. package/dist/esm/airgap-instances.js.map +1 -1
  63. package/dist/esm/error-page.js +10 -2
  64. package/dist/esm/error-page.js.map +1 -1
  65. package/dist/esm/error.js +10 -2
  66. package/dist/esm/error.js.map +1 -1
  67. package/dist/esm/helm-install-wizard.js +127 -81
  68. package/dist/esm/helm-install-wizard.js.map +1 -1
  69. package/dist/esm/index.js +706 -438
  70. package/dist/esm/index.js.map +1 -1
  71. package/dist/esm/install-actions.js +40 -5
  72. package/dist/esm/install-actions.js.map +1 -1
  73. package/dist/esm/install-card.js +9 -6
  74. package/dist/esm/install-card.js.map +1 -1
  75. package/dist/esm/install-targets.js +9 -2
  76. package/dist/esm/install-targets.js.map +1 -1
  77. package/dist/esm/instance-card.js +175 -31
  78. package/dist/esm/instance-card.js.map +1 -1
  79. package/dist/esm/join-team.js +9 -3
  80. package/dist/esm/join-team.js.map +1 -1
  81. package/dist/esm/license-card.js +24 -22
  82. package/dist/esm/license-card.js.map +1 -1
  83. package/dist/esm/license-details.js +128 -334
  84. package/dist/esm/license-details.js.map +1 -1
  85. package/dist/esm/linux-install-wizard.js +219 -133
  86. package/dist/esm/linux-install-wizard.js.map +1 -1
  87. package/dist/esm/login.js +20 -4
  88. package/dist/esm/login.js.map +1 -1
  89. package/dist/esm/middleware.js +33 -0
  90. package/dist/esm/middleware.js.map +1 -0
  91. package/dist/esm/online-instance-list.js +176 -32
  92. package/dist/esm/online-instance-list.js.map +1 -1
  93. package/dist/esm/pending-installations.js +4 -3
  94. package/dist/esm/pending-installations.js.map +1 -1
  95. package/dist/esm/release-history-panel.js +27 -14
  96. package/dist/esm/release-history-panel.js.map +1 -1
  97. package/dist/esm/saml-callback-client.js +82 -0
  98. package/dist/esm/saml-callback-client.js.map +1 -0
  99. package/dist/esm/saml-handlers.js +138 -0
  100. package/dist/esm/saml-handlers.js.map +1 -0
  101. package/dist/esm/security-card.js +53 -38
  102. package/dist/esm/security-card.js.map +1 -1
  103. package/dist/esm/service-accounts-tab.js +800 -0
  104. package/dist/esm/service-accounts-tab.js.map +1 -0
  105. package/dist/esm/support-bundle-collection-card.js +55 -25
  106. package/dist/esm/support-bundle-collection-card.js.map +1 -1
  107. package/dist/esm/support-bundles-card.js +10 -5
  108. package/dist/esm/support-bundles-card.js.map +1 -1
  109. package/dist/esm/support-card.js +37 -5
  110. package/dist/esm/support-card.js.map +1 -1
  111. package/dist/esm/team-selection.js +5 -1
  112. package/dist/esm/team-selection.js.map +1 -1
  113. package/dist/esm/team-settings-card.js +5 -2
  114. package/dist/esm/team-settings-card.js.map +1 -1
  115. package/dist/esm/team-settings.js +7 -2
  116. package/dist/esm/team-settings.js.map +1 -1
  117. package/dist/esm/top-nav-user-menu.js +5 -1
  118. package/dist/esm/top-nav-user-menu.js.map +1 -1
  119. package/dist/esm/top-nav.js +175 -62
  120. package/dist/esm/top-nav.js.map +1 -1
  121. package/dist/esm/trial-signup.js +256 -0
  122. package/dist/esm/trial-signup.js.map +1 -0
  123. package/dist/esm/update-layout.js +175 -62
  124. package/dist/esm/update-layout.js.map +1 -1
  125. package/dist/esm/updates-card.js +15 -4
  126. package/dist/esm/updates-card.js.map +1 -1
  127. package/dist/esm/upload-support-bundle-modal.js +9 -4
  128. package/dist/esm/upload-support-bundle-modal.js.map +1 -1
  129. package/dist/esm/user-settings-card.js +5 -2
  130. package/dist/esm/user-settings-card.js.map +1 -1
  131. package/dist/esm/user-settings.js +12 -6
  132. package/dist/esm/user-settings.js.map +1 -1
  133. package/dist/esm/utils/index.js +204 -13
  134. package/dist/esm/utils/index.js.map +1 -1
  135. package/dist/fetch-license-iTyF7_GY.d.mts +81 -0
  136. package/dist/fetch-license-iTyF7_GY.d.ts +81 -0
  137. package/dist/helm-install-wizard.d.mts +12 -3
  138. package/dist/helm-install-wizard.d.ts +12 -3
  139. package/dist/helm-install-wizard.js +127 -81
  140. package/dist/helm-install-wizard.js.map +1 -1
  141. package/dist/{index-DkjaogsF.d.ts → index-DyzJ0yKD.d.mts} +194 -49
  142. package/dist/{index-DkjaogsF.d.mts → index-sMbq94M7.d.ts} +194 -49
  143. package/dist/index.d.mts +9 -2
  144. package/dist/index.d.ts +9 -2
  145. package/dist/index.js +726 -438
  146. package/dist/index.js.map +1 -1
  147. package/dist/install-actions.d.mts +5 -2
  148. package/dist/install-actions.d.ts +5 -2
  149. package/dist/install-actions.js +40 -5
  150. package/dist/install-actions.js.map +1 -1
  151. package/dist/install-card.d.mts +2 -2
  152. package/dist/install-card.d.ts +2 -2
  153. package/dist/install-card.js +9 -6
  154. package/dist/install-card.js.map +1 -1
  155. package/dist/install-targets.js +9 -2
  156. package/dist/install-targets.js.map +1 -1
  157. package/dist/instance-card.d.mts +4 -1
  158. package/dist/instance-card.d.ts +4 -1
  159. package/dist/instance-card.js +176 -31
  160. package/dist/instance-card.js.map +1 -1
  161. package/dist/join-team.js +9 -3
  162. package/dist/join-team.js.map +1 -1
  163. package/dist/license-card.d.mts +2 -2
  164. package/dist/license-card.d.ts +2 -2
  165. package/dist/license-card.js +24 -22
  166. package/dist/license-card.js.map +1 -1
  167. package/dist/license-details.js +128 -334
  168. package/dist/license-details.js.map +1 -1
  169. package/dist/linux-install-wizard.d.mts +12 -6
  170. package/dist/linux-install-wizard.d.ts +12 -6
  171. package/dist/linux-install-wizard.js +219 -133
  172. package/dist/linux-install-wizard.js.map +1 -1
  173. package/dist/login.d.mts +4 -0
  174. package/dist/login.d.ts +4 -0
  175. package/dist/login.js +20 -4
  176. package/dist/login.js.map +1 -1
  177. package/dist/middleware.d.mts +13 -0
  178. package/dist/middleware.d.ts +13 -0
  179. package/dist/middleware.js +35 -0
  180. package/dist/middleware.js.map +1 -0
  181. package/dist/online-instance-list.d.mts +4 -1
  182. package/dist/online-instance-list.d.ts +4 -1
  183. package/dist/online-instance-list.js +177 -32
  184. package/dist/online-instance-list.js.map +1 -1
  185. package/dist/pending-installations.d.mts +8 -3
  186. package/dist/pending-installations.d.ts +8 -3
  187. package/dist/pending-installations.js +4 -3
  188. package/dist/pending-installations.js.map +1 -1
  189. package/dist/release-history-panel.js +27 -14
  190. package/dist/release-history-panel.js.map +1 -1
  191. package/dist/saml-callback-client.d.mts +36 -0
  192. package/dist/saml-callback-client.d.ts +36 -0
  193. package/dist/saml-callback-client.js +88 -0
  194. package/dist/saml-callback-client.js.map +1 -0
  195. package/dist/saml-handlers.d.mts +50 -0
  196. package/dist/saml-handlers.d.ts +50 -0
  197. package/dist/saml-handlers.js +141 -0
  198. package/dist/saml-handlers.js.map +1 -0
  199. package/dist/security-card.d.mts +4 -1
  200. package/dist/security-card.d.ts +4 -1
  201. package/dist/security-card.js +53 -38
  202. package/dist/security-card.js.map +1 -1
  203. package/dist/service-accounts-tab.d.mts +51 -0
  204. package/dist/service-accounts-tab.d.ts +51 -0
  205. package/dist/service-accounts-tab.js +802 -0
  206. package/dist/service-accounts-tab.js.map +1 -0
  207. package/dist/styles.css +380 -143
  208. package/dist/support-bundle-collection-card.d.mts +1 -1
  209. package/dist/support-bundle-collection-card.d.ts +1 -1
  210. package/dist/support-bundle-collection-card.js +54 -24
  211. package/dist/support-bundle-collection-card.js.map +1 -1
  212. package/dist/support-bundles-card.d.mts +5 -2
  213. package/dist/support-bundles-card.d.ts +5 -2
  214. package/dist/support-bundles-card.js +10 -5
  215. package/dist/support-bundles-card.js.map +1 -1
  216. package/dist/support-card.js +37 -5
  217. package/dist/support-card.js.map +1 -1
  218. package/dist/team-selection.js +5 -1
  219. package/dist/team-selection.js.map +1 -1
  220. package/dist/team-settings-card.js +5 -2
  221. package/dist/team-settings-card.js.map +1 -1
  222. package/dist/team-settings.js +7 -2
  223. package/dist/team-settings.js.map +1 -1
  224. package/dist/{top-nav-IRIn66wS.d.ts → top-nav-BUQAGoG1.d.mts} +14 -2
  225. package/dist/{top-nav-IRIn66wS.d.mts → top-nav-CEqw0KpO.d.ts} +14 -2
  226. package/dist/top-nav-user-menu.js +5 -1
  227. package/dist/top-nav-user-menu.js.map +1 -1
  228. package/dist/top-nav.d.mts +2 -1
  229. package/dist/top-nav.d.ts +2 -1
  230. package/dist/top-nav.js +175 -62
  231. package/dist/top-nav.js.map +1 -1
  232. package/dist/trial-signup.d.mts +31 -0
  233. package/dist/trial-signup.d.ts +31 -0
  234. package/dist/trial-signup.js +258 -0
  235. package/dist/trial-signup.js.map +1 -0
  236. package/dist/update-layout.js +175 -62
  237. package/dist/update-layout.js.map +1 -1
  238. package/dist/updates-card.js +15 -4
  239. package/dist/updates-card.js.map +1 -1
  240. package/dist/upload-support-bundle-modal.js +9 -4
  241. package/dist/upload-support-bundle-modal.js.map +1 -1
  242. package/dist/user-settings-card.js +5 -2
  243. package/dist/user-settings-card.js.map +1 -1
  244. package/dist/user-settings.js +12 -6
  245. package/dist/user-settings.js.map +1 -1
  246. package/dist/utils/index.d.mts +74 -16
  247. package/dist/utils/index.d.ts +74 -16
  248. package/dist/utils/index.js +215 -12
  249. package/dist/utils/index.js.map +1 -1
  250. package/package.json +67 -1
@@ -2,14 +2,127 @@
2
2
 
3
3
  var buffer = require('buffer');
4
4
  var react = require('react');
5
+ var headers = require('next/headers');
6
+ var cache = require('next/cache');
5
7
 
6
8
  /**
7
9
  * Enterprise Portal Components
8
10
  * This file is generated by tsup. Do not edit manually.
9
11
  */
12
+ var __defProp = Object.defineProperty;
13
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
14
+ var __getOwnPropNames = Object.getOwnPropertyNames;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
17
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
18
+ }) : x)(function(x) {
19
+ if (typeof require !== "undefined") return require.apply(this, arguments);
20
+ throw Error('Dynamic require of "' + x + '" is not supported');
21
+ });
22
+ var __esm = (fn, res) => function __init() {
23
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
24
+ };
25
+ var __export = (target, all) => {
26
+ for (var name in all)
27
+ __defProp(target, name, { get: all[name], enumerable: true });
28
+ };
29
+ var __copyProps = (to, from, except, desc) => {
30
+ if (from && typeof from === "object" || typeof from === "function") {
31
+ for (let key of __getOwnPropNames(from))
32
+ if (!__hasOwnProp.call(to, key) && key !== except)
33
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
34
+ }
35
+ return to;
36
+ };
37
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
10
38
 
39
+ // datadog/tracer.ts
40
+ var tracer_exports = {};
41
+ __export(tracer_exports, {
42
+ default: () => tracer_default
43
+ });
44
+ var rawFlag, isEnabled, tracer, getRoutePattern, tracer_default;
45
+ var init_tracer = __esm({
46
+ "datadog/tracer.ts"() {
47
+ rawFlag = String(process.env.USE_DATADOG_APM || "").toLowerCase();
48
+ isEnabled = rawFlag === "true";
49
+ process.env.DD_TRACE_ENABLED = isEnabled ? "1" : "0";
50
+ tracer = null;
51
+ if (isEnabled) {
52
+ const serviceName = process.env.DD_SERVICE || "enterprise-portal";
53
+ const environment = process.env.DD_ENV || process.env.NODE_ENV || "development";
54
+ const version = process.env.DD_VERSION || process.env.NEXT_PUBLIC_VERSION || "0.0.0-dev";
55
+ const agentHost = process.env.DD_AGENT_HOST || process.env.DATADOG_AGENT_HOST || "127.0.0.1";
56
+ const agentPort = process.env.DD_TRACE_AGENT_PORT || "8126";
57
+ process.env.DD_SERVICE = serviceName;
58
+ process.env.DD_ENV = environment;
59
+ {
60
+ process.env.DD_VERSION = version;
61
+ }
62
+ process.env.DD_AGENT_HOST = agentHost;
63
+ process.env.DD_TRACE_AGENT_PORT = agentPort;
64
+ const dbmPropagationMode = process.env.DD_DBM_PROPAGATION_MODE || "full";
65
+ process.env.DD_DBM_PROPAGATION_MODE = dbmPropagationMode;
66
+ try {
67
+ const ddTrace = __require("dd-trace");
68
+ tracer = ddTrace.init({
69
+ service: serviceName,
70
+ env: environment,
71
+ version,
72
+ logInjection: true,
73
+ runtimeMetrics: true,
74
+ appsec: false,
75
+ profiling: false,
76
+ startupLogs: true
77
+ // Enable for debugging
78
+ });
79
+ console.log(`[datadog] Tracer initialized: service=${serviceName}, env=${environment}, version=${version}, agent=${agentHost}:${agentPort}`);
80
+ tracer.use("dns", false);
81
+ tracer.use("net", false);
82
+ tracer.use("http", {
83
+ server: {
84
+ hooks: {
85
+ request: (span, req) => {
86
+ if (!span) return;
87
+ const url = req?.url || "";
88
+ const method = req?.method || "GET";
89
+ const path = url.split("?")[0];
90
+ if (path.startsWith("/_next/")) {
91
+ span.context()._trace.isRecording = false;
92
+ return;
93
+ }
94
+ const routePattern = getRoutePattern(path);
95
+ span.setTag("resource.name", `${method} ${routePattern}`);
96
+ span.setTag("http.route", routePattern);
97
+ }
98
+ }
99
+ }
100
+ });
101
+ } catch (err) {
102
+ console.error("[datadog] failed to initialize tracing", err);
103
+ tracer = null;
104
+ }
105
+ }
106
+ getRoutePattern = (path) => {
107
+ const routePatterns = [
108
+ // Update instance routes - normalize dynamic segments (capture suffix to preserve sub-routes)
109
+ { pattern: /^\/update\/instance\/[^/]+(.*)$/, replacement: "/update/instance/[instanceId]$1" }
110
+ ];
111
+ for (const { pattern, replacement } of routePatterns) {
112
+ if (pattern.test(path)) {
113
+ return path.replace(pattern, replacement);
114
+ }
115
+ }
116
+ return path;
117
+ };
118
+ tracer_default = tracer;
119
+ }
120
+ });
11
121
 
12
122
  // src/utils/api-client.ts
123
+ function isRedirectError(error) {
124
+ return typeof error === "object" && error !== null && "digest" in error && typeof error.digest === "string" && error.digest.startsWith("NEXT_REDIRECT");
125
+ }
13
126
  async function authenticatedFetch(url, options = {}) {
14
127
  const { token, ...fetchOptions } = options;
15
128
  const headers = new Headers(fetchOptions.headers);
@@ -32,8 +145,17 @@ async function handle401() {
32
145
  const { redirect } = await import('next/navigation');
33
146
  return redirect("/?expired=1");
34
147
  }
148
+ function isErrorPage(url) {
149
+ try {
150
+ const urlObj = new URL(url);
151
+ return urlObj.pathname === "/error";
152
+ } catch {
153
+ return url === "/error" || url.startsWith("/error?");
154
+ }
155
+ }
35
156
  async function handleServerError(statusCode) {
36
157
  const { redirect } = await import('next/navigation');
158
+ const { cookies: cookies9 } = await import('next/headers');
37
159
  let sourceUrl;
38
160
  try {
39
161
  const { headers } = await import('next/headers');
@@ -41,12 +163,20 @@ async function handleServerError(statusCode) {
41
163
  const referer = headersList.get("referer");
42
164
  const host = headersList.get("host");
43
165
  const pathname = headersList.get("x-invoke-path") || headersList.get("x-forwarded-path");
44
- if (referer) {
166
+ if (referer && !isErrorPage(referer)) {
45
167
  sourceUrl = referer;
46
168
  } else if (host && pathname) {
47
169
  const protocol = headersList.get("x-forwarded-proto") || "https";
48
170
  sourceUrl = `${protocol}://${host}${pathname}`;
49
171
  }
172
+ if (!sourceUrl || isErrorPage(sourceUrl)) {
173
+ const cookieStore = await cookies9();
174
+ const preservedSource = cookieStore.get("portal_error_source");
175
+ if (preservedSource?.value) {
176
+ sourceUrl = decodeURIComponent(preservedSource.value);
177
+ cookieStore.delete("portal_error_source");
178
+ }
179
+ }
50
180
  } catch (error) {
51
181
  console.debug("[portal-components] Could not determine source URL", error);
52
182
  }
@@ -57,6 +187,1039 @@ async function handleServerError(statusCode) {
57
187
  return redirect(`/error?${params.toString()}`);
58
188
  }
59
189
 
190
+ // src/utils/observability/tracing.ts
191
+ var tracerCache = void 0;
192
+ function getTracer() {
193
+ if (tracerCache !== void 0) {
194
+ return tracerCache;
195
+ }
196
+ const rawFlag2 = String(process.env.USE_DATADOG_APM || "").toLowerCase();
197
+ const isEnabled2 = rawFlag2 === "true";
198
+ if (!isEnabled2) {
199
+ tracerCache = null;
200
+ return null;
201
+ }
202
+ try {
203
+ const tracerModule = (init_tracer(), __toCommonJS(tracer_exports));
204
+ const tracer2 = tracerModule.default || tracerModule;
205
+ if (tracer2 && typeof tracer2.trace === "function") {
206
+ tracerCache = tracer2;
207
+ return tracerCache;
208
+ }
209
+ } catch (err) {
210
+ console.warn("Failed to load tracer:", err);
211
+ }
212
+ tracerCache = null;
213
+ return null;
214
+ }
215
+ async function withTrace(name, fn) {
216
+ const activeTracer = getTracer();
217
+ if (!activeTracer) {
218
+ return fn(void 0);
219
+ }
220
+ return activeTracer.trace(name, async (span) => {
221
+ if (span) {
222
+ span.setTag("component", "application");
223
+ }
224
+ try {
225
+ const result = await fn(span);
226
+ return result;
227
+ } catch (error) {
228
+ if (span) {
229
+ span.setTag("error", error);
230
+ }
231
+ throw error;
232
+ }
233
+ });
234
+ }
235
+ function traceServerAction(name, fn) {
236
+ const spanName = name.startsWith("server.action.") ? name : `server.action.${name}`;
237
+ const traced = async (...args) => {
238
+ return withTrace(spanName, async (span) => {
239
+ if (span) {
240
+ span.setTag("component", "server-action");
241
+ }
242
+ const result = await fn(...args);
243
+ return result;
244
+ });
245
+ };
246
+ return traced;
247
+ }
248
+ var deriveInstallMethods = (licenseData) => {
249
+ const methods = [];
250
+ if (licenseData.isKotsInstallEnabled) {
251
+ methods.push("Replicated KOTS");
252
+ }
253
+ if (licenseData.isHelmInstallEnabled) {
254
+ methods.push("Helm");
255
+ }
256
+ if (licenseData.isHelmAirgapEnabled) {
257
+ methods.push("Helm Airgap");
258
+ }
259
+ if (licenseData.isEmbeddedClusterDownloadEnabled || licenseData.isEmbeddedClusterMultiNodeEnabled) {
260
+ methods.push("Embedded Cluster");
261
+ }
262
+ if (licenseData.isKurlInstallEnabled) {
263
+ methods.push("kURL");
264
+ }
265
+ if (licenseData.isGitopsSupported) {
266
+ methods.push("GitOps");
267
+ }
268
+ return Array.from(new Set(methods));
269
+ };
270
+ var convertEntitlementsToFields = (entitlementFields, entitlementValues) => {
271
+ const valuesMap = /* @__PURE__ */ new Map();
272
+ entitlementValues.forEach((ev) => {
273
+ valuesMap.set(ev.name, ev.value);
274
+ });
275
+ return entitlementFields.filter((field) => field.hidden === 0).map((field) => ({
276
+ key: field.name,
277
+ label: field.title || field.name,
278
+ value: valuesMap.get(field.name) || field.defaultVal || null,
279
+ isSecret: field.type === "Password"
280
+ }));
281
+ };
282
+ async function fetchLicenseCore() {
283
+ const sessionStore = await headers.cookies();
284
+ const session = sessionStore.get("portal_session");
285
+ const token = session?.value;
286
+ if (!token) {
287
+ throw new Error("No session found - user must be authenticated");
288
+ }
289
+ const endpoint = `${getApiOrigin()}/enterprise-portal/license`;
290
+ if (process.env.NODE_ENV !== "production") {
291
+ console.debug("[portal-components] fetching license via %s (Enterprise Portal API)", endpoint);
292
+ }
293
+ const response = await authenticatedFetch(endpoint, {
294
+ method: "GET",
295
+ token,
296
+ headers: {
297
+ Accept: "application/json"
298
+ }
299
+ });
300
+ if (!response.ok) {
301
+ throw new Error(
302
+ `License request failed (${response.status} ${response.statusText})`
303
+ );
304
+ }
305
+ const envelope = await response.json();
306
+ const licenseData = envelope.data;
307
+ const license = {
308
+ ...licenseData,
309
+ // Alias fields for backward compatibility
310
+ expiresAt: licenseData.expireAt,
311
+ environment: licenseData.licenseType,
312
+ // Extract channel names from channels array
313
+ releaseChannels: (licenseData.channels || []).map((ch) => ch.channelName),
314
+ // Derive install methods from feature flags
315
+ installMethods: deriveInstallMethods(licenseData),
316
+ // Convert entitlements to fields format
317
+ fields: convertEntitlementsToFields(licenseData.entitlementFields || [], licenseData.entitlementValues || [])
318
+ };
319
+ return license;
320
+ }
321
+ var fetchLicenseImpl = react.cache(fetchLicenseCore);
322
+ var fetchLicense = fetchLicenseImpl;
323
+
324
+ // src/actions/install.ts
325
+ async function fetchChannelReleases(input, context) {
326
+ const { token, channelId } = input;
327
+ if (!token || typeof token !== "string") {
328
+ throw new Error("fetchChannelReleases requires a session token");
329
+ }
330
+ const origin = getApiOrigin();
331
+ const url = new URL(`${origin}/enterprise-portal/channel-releases`);
332
+ if (channelId) {
333
+ url.searchParams.set("channel_id", channelId);
334
+ }
335
+ if (process.env.NODE_ENV !== "production") {
336
+ console.debug("[portal-components] fetching channel releases via %s (Enterprise Portal API)", url.toString());
337
+ }
338
+ const response = await authenticatedFetch(url.toString(), {
339
+ method: "GET",
340
+ token,
341
+ headers: {
342
+ accept: "application/json"
343
+ },
344
+ signal: context?.signal
345
+ });
346
+ if (!response.ok) {
347
+ const errorText = await response.text();
348
+ throw new Error(
349
+ `Channel releases request failed (${response.status} ${response.statusText}): ${errorText}`
350
+ );
351
+ }
352
+ const envelope = await response.json();
353
+ const payload = envelope.data;
354
+ return {
355
+ channelReleases: payload?.channelReleases || []
356
+ };
357
+ }
358
+ async function createInstallOptions(input, context) {
359
+ const {
360
+ token,
361
+ installType,
362
+ instanceName,
363
+ serviceAccountId,
364
+ networkAvailability,
365
+ isMultiNode = false,
366
+ channelId,
367
+ channelReleaseSequence,
368
+ registryAvailability,
369
+ kubernetesDistribution
370
+ } = input;
371
+ if (!token || typeof token !== "string") {
372
+ throw new Error("createInstallOptions requires a session token");
373
+ }
374
+ if (!instanceName?.trim()) {
375
+ throw new Error("Instance name is required");
376
+ }
377
+ if (!serviceAccountId?.trim()) {
378
+ throw new Error("Service account ID is required");
379
+ }
380
+ const origin = getApiOrigin();
381
+ const endpoint = `${origin}/enterprise-portal/install-options?includeInstructions=true`;
382
+ const body = {
383
+ install_type: installType,
384
+ instance_name: instanceName.trim(),
385
+ service_account_id: serviceAccountId.trim(),
386
+ network_availability: networkAvailability,
387
+ is_multi_node: isMultiNode
388
+ };
389
+ if (channelId) {
390
+ body.channel_id = channelId;
391
+ }
392
+ if (channelReleaseSequence !== void 0) {
393
+ body.channel_release_sequence = channelReleaseSequence;
394
+ }
395
+ if (registryAvailability) {
396
+ body.registry_availability = registryAvailability;
397
+ }
398
+ if (kubernetesDistribution) {
399
+ body.kubernetes_distribution = kubernetesDistribution;
400
+ }
401
+ if (process.env.NODE_ENV !== "production") {
402
+ console.debug("[portal-components] creating install options via %s", endpoint);
403
+ }
404
+ const response = await authenticatedFetch(endpoint, {
405
+ method: "POST",
406
+ token,
407
+ headers: {
408
+ "content-type": "application/json",
409
+ accept: "application/json"
410
+ },
411
+ body: JSON.stringify(body),
412
+ signal: context?.signal
413
+ });
414
+ if (!response.ok) {
415
+ const errorText = await response.text();
416
+ throw new Error(
417
+ `Create install options failed (${response.status} ${response.statusText}): ${errorText}`
418
+ );
419
+ }
420
+ return await response.json();
421
+ }
422
+ async function getInstallOptions(input, context) {
423
+ const {
424
+ token,
425
+ installOptionsId,
426
+ includeInstructions = true,
427
+ privateRegistryHostname,
428
+ proxyUrl
429
+ } = input;
430
+ if (!token || typeof token !== "string") {
431
+ throw new Error("getInstallOptions requires a session token");
432
+ }
433
+ if (!installOptionsId?.trim()) {
434
+ throw new Error("Install options ID is required");
435
+ }
436
+ const origin = getApiOrigin();
437
+ const url = new URL(`${origin}/enterprise-portal/install-options/${installOptionsId.trim()}`);
438
+ if (includeInstructions) {
439
+ url.searchParams.set("includeInstructions", "true");
440
+ }
441
+ if (privateRegistryHostname) {
442
+ url.searchParams.set("privateRegistryHostname", privateRegistryHostname);
443
+ }
444
+ if (proxyUrl) {
445
+ url.searchParams.set("proxyUrl", proxyUrl);
446
+ }
447
+ if (process.env.NODE_ENV !== "production") {
448
+ console.debug("[portal-components] fetching install options via %s (Enterprise Portal API)", url.toString());
449
+ }
450
+ const response = await authenticatedFetch(url.toString(), {
451
+ method: "GET",
452
+ token,
453
+ headers: {
454
+ accept: "application/json"
455
+ },
456
+ signal: context?.signal
457
+ });
458
+ if (!response.ok) {
459
+ const errorText = await response.text();
460
+ throw new Error(
461
+ `Get install options failed (${response.status} ${response.statusText}): ${errorText}`
462
+ );
463
+ }
464
+ const envelope = await response.json();
465
+ return envelope.data;
466
+ }
467
+ async function updateInstallOptions(input, context) {
468
+ const {
469
+ token,
470
+ installOptionsId,
471
+ installType,
472
+ channelId,
473
+ channelReleaseSequence,
474
+ networkAvailability,
475
+ registryAvailability,
476
+ kubernetesDistribution,
477
+ isMultiNode,
478
+ serviceAccountId,
479
+ adminConsoleUrl,
480
+ status,
481
+ includeInstructions = true,
482
+ privateRegistryHostname,
483
+ proxyUrl
484
+ } = input;
485
+ if (!token || typeof token !== "string") {
486
+ throw new Error("updateInstallOptions requires a session token");
487
+ }
488
+ if (!installOptionsId?.trim()) {
489
+ throw new Error("Install options ID is required");
490
+ }
491
+ const origin = getApiOrigin();
492
+ const url = new URL(`${origin}/enterprise-portal/install-options/${installOptionsId.trim()}`);
493
+ if (includeInstructions) {
494
+ url.searchParams.set("includeInstructions", "true");
495
+ }
496
+ if (privateRegistryHostname) {
497
+ url.searchParams.set("privateRegistryHostname", privateRegistryHostname);
498
+ }
499
+ if (proxyUrl) {
500
+ url.searchParams.set("proxyUrl", proxyUrl);
501
+ }
502
+ const body = {};
503
+ if (installType !== void 0) {
504
+ body.install_type = installType;
505
+ }
506
+ if (channelId !== void 0) {
507
+ body.channel_id = channelId;
508
+ }
509
+ if (channelReleaseSequence !== void 0) {
510
+ body.channel_release_sequence = channelReleaseSequence;
511
+ }
512
+ if (networkAvailability !== void 0) {
513
+ body.network_availability = networkAvailability;
514
+ }
515
+ if (registryAvailability !== void 0) {
516
+ body.registry_availability = registryAvailability;
517
+ }
518
+ if (kubernetesDistribution !== void 0) {
519
+ body.kubernetes_distribution = kubernetesDistribution;
520
+ }
521
+ if (isMultiNode !== void 0) {
522
+ body.is_multi_node = isMultiNode;
523
+ }
524
+ if (serviceAccountId !== void 0) {
525
+ body.service_account_id = serviceAccountId;
526
+ }
527
+ if (adminConsoleUrl !== void 0) {
528
+ body.admin_console_url = adminConsoleUrl;
529
+ }
530
+ if (status !== void 0) {
531
+ body.status = status;
532
+ }
533
+ if (process.env.NODE_ENV !== "production") {
534
+ console.debug("[portal-components] updating install options via %s", url.toString());
535
+ }
536
+ const response = await authenticatedFetch(url.toString(), {
537
+ method: "PATCH",
538
+ token,
539
+ headers: {
540
+ "content-type": "application/json",
541
+ accept: "application/json"
542
+ },
543
+ body: JSON.stringify(body),
544
+ signal: context?.signal
545
+ });
546
+ if (!response.ok) {
547
+ const errorText = await response.text();
548
+ throw new Error(
549
+ `Update install options failed (${response.status} ${response.statusText}): ${errorText}`
550
+ );
551
+ }
552
+ return await response.json();
553
+ }
554
+ async function fetchPendingInstallations(input, context) {
555
+ const { token } = input;
556
+ if (typeof token !== "string" || token.trim().length === 0) {
557
+ throw new Error("fetchPendingInstallations requires a non-empty token");
558
+ }
559
+ const origin = getApiOrigin();
560
+ const queryParams = new URLSearchParams();
561
+ queryParams.set("status", "in_progress");
562
+ queryParams.set("page_size", "5");
563
+ queryParams.set("order_by", "created_at");
564
+ queryParams.set("order_direction", "desc");
565
+ const endpoint = `${origin}/enterprise-portal/install-options?${queryParams.toString()}`;
566
+ if (process.env.NODE_ENV !== "production") {
567
+ console.debug("[portal-components] fetching pending installations via %s (Enterprise Portal API)", endpoint);
568
+ }
569
+ const response = await authenticatedFetch(endpoint, {
570
+ method: "GET",
571
+ token,
572
+ headers: {
573
+ accept: "application/json"
574
+ },
575
+ signal: context?.signal
576
+ });
577
+ if (!response.ok) {
578
+ throw new Error(
579
+ `Pending installations request failed (${response.status} ${response.statusText})`
580
+ );
581
+ }
582
+ const envelope = await response.json();
583
+ const payload = envelope.data;
584
+ const installArray = payload?.install_options || [];
585
+ const installations = installArray.map((item) => ({
586
+ id: String(item.id || ""),
587
+ name: String(item.instance_name || "Unknown"),
588
+ method: item.install_type === "helm" ? "helm" : "linux",
589
+ startedBy: String(item.service_account_email_address || "Unknown"),
590
+ startedAt: String(item.started_at || (/* @__PURE__ */ new Date()).toISOString())
591
+ }));
592
+ return {
593
+ installations
594
+ };
595
+ }
596
+ async function discardInstallation(input, context) {
597
+ const { token, installOptionsId } = input;
598
+ if (typeof token !== "string" || token.trim().length === 0) {
599
+ throw new Error("discardInstallation requires a non-empty token");
600
+ }
601
+ if (typeof installOptionsId !== "string" || installOptionsId.trim().length === 0) {
602
+ throw new Error("discardInstallation requires a non-empty installOptionsId");
603
+ }
604
+ const origin = getApiOrigin();
605
+ const response = await authenticatedFetch(
606
+ `${origin}/enterprise-portal/install-options/${installOptionsId.trim()}`,
607
+ {
608
+ method: "DELETE",
609
+ token,
610
+ headers: {
611
+ accept: "application/json"
612
+ },
613
+ signal: context?.signal
614
+ }
615
+ );
616
+ if (!response.ok) {
617
+ const errorText = await response.text();
618
+ throw new Error(
619
+ `Discard install options failed (${response.status} ${response.statusText}): ${errorText}`
620
+ );
621
+ }
622
+ return {
623
+ success: true
624
+ };
625
+ }
626
+
627
+ // src/actions/install-actions.ts
628
+ async function fetchPendingInstallationsActionImpl() {
629
+ const sessionStore = await headers.cookies();
630
+ const session = sessionStore.get("portal_session");
631
+ const token = session?.value || "";
632
+ if (!token) {
633
+ return { installations: [] };
634
+ }
635
+ return fetchPendingInstallations({ token });
636
+ }
637
+ var fetchPendingInstallationsAction = traceServerAction("fetchPendingInstallationsAction", fetchPendingInstallationsActionImpl);
638
+ async function fetchChannelReleasesActionImpl(token, channelId) {
639
+ return fetchChannelReleases({ token, channelId });
640
+ }
641
+ var fetchChannelReleasesAction = traceServerAction("fetchChannelReleasesAction", fetchChannelReleasesActionImpl);
642
+ async function createInstallOptionsActionImpl(input) {
643
+ return createInstallOptions(input);
644
+ }
645
+ var createInstallOptionsAction = traceServerAction("createInstallOptionsAction", createInstallOptionsActionImpl);
646
+ async function getInstallOptionsActionImpl(input) {
647
+ return getInstallOptions({
648
+ ...input,
649
+ includeInstructions: input.includeInstructions ?? true
650
+ });
651
+ }
652
+ var getInstallOptionsAction = traceServerAction("getInstallOptionsAction", getInstallOptionsActionImpl);
653
+ async function updateInstallOptionsActionImpl(input) {
654
+ return updateInstallOptions({
655
+ ...input,
656
+ includeInstructions: input.includeInstructions ?? true
657
+ });
658
+ }
659
+ var updateInstallOptionsAction = traceServerAction("updateInstallOptionsAction", updateInstallOptionsActionImpl);
660
+ async function discardInstallationActionImpl(installOptionsId) {
661
+ const sessionStore = await headers.cookies();
662
+ const session = sessionStore.get("portal_session");
663
+ const token = session?.value || "";
664
+ if (!token) {
665
+ throw new Error("Authentication required");
666
+ }
667
+ return discardInstallation({ token, installOptionsId });
668
+ }
669
+ var discardInstallationAction = traceServerAction("discardInstallationAction", discardInstallationActionImpl);
670
+
671
+ // src/actions/service-account.ts
672
+ async function createServiceAccountActionImpl(name, token) {
673
+ return createServiceAccount.run({ name, token });
674
+ }
675
+ var createServiceAccountAction = traceServerAction("createServiceAccountAction", createServiceAccountActionImpl);
676
+ async function fetchAppInfoImpl() {
677
+ let appName = "Application";
678
+ let channelName = "";
679
+ const sessionStore = await headers.cookies();
680
+ const session = sessionStore.get("portal_session");
681
+ const token = session?.value;
682
+ if (!token) {
683
+ return { appName, channelName };
684
+ }
685
+ try {
686
+ const branding = await fetchCustomBranding();
687
+ if (branding?.brandingData) {
688
+ const decoded = buffer.Buffer.from(branding.brandingData, "base64").toString("utf-8");
689
+ const brandingObj = JSON.parse(decoded);
690
+ if (brandingObj.title) {
691
+ appName = brandingObj.title;
692
+ }
693
+ }
694
+ } catch (error) {
695
+ console.error("[fetch-app-info] fetchCustomBranding failed", error);
696
+ }
697
+ const license = await fetchLicense();
698
+ if (license?.releaseChannels && license.releaseChannels.length > 0) {
699
+ const channel = license.releaseChannels[0];
700
+ if (channel) {
701
+ channelName = channel;
702
+ }
703
+ }
704
+ return { appName, channelName };
705
+ }
706
+ var fetchAppInfo = traceServerAction("fetchAppInfo", fetchAppInfoImpl);
707
+ async function fetchTeamUsersActionImpl(limit = 25, offset = 0) {
708
+ const sessionStore = await headers.cookies();
709
+ const session = sessionStore.get("portal_session");
710
+ if (!session?.value) {
711
+ throw new Error("No session found");
712
+ }
713
+ const result = await fetchTeamUsers.run({
714
+ token: session.value,
715
+ limit,
716
+ offset
717
+ });
718
+ let currentUserEmail;
719
+ try {
720
+ const payload = decodeJwtPayload(session.value);
721
+ currentUserEmail = payload?.email;
722
+ } catch {
723
+ }
724
+ return {
725
+ users: result.users,
726
+ total: result.total,
727
+ currentUserEmail
728
+ };
729
+ }
730
+ var fetchTeamUsersAction = traceServerAction("fetchTeamUsersAction", fetchTeamUsersActionImpl);
731
+ async function inviteUserActionImpl(email) {
732
+ const sessionStore = await headers.cookies();
733
+ const session = sessionStore.get("portal_session");
734
+ if (!session?.value) {
735
+ throw new Error("No session found");
736
+ }
737
+ await inviteUser.run({
738
+ token: session.value,
739
+ email
740
+ });
741
+ cache.revalidatePath("/team-settings");
742
+ return { success: true };
743
+ }
744
+ var inviteUserAction = traceServerAction("inviteUserAction", inviteUserActionImpl);
745
+ async function deleteUserActionImpl(id, isPendingInvite) {
746
+ const sessionStore = await headers.cookies();
747
+ const session = sessionStore.get("portal_session");
748
+ if (!session?.value) {
749
+ throw new Error("No session found");
750
+ }
751
+ await deleteUser.run({
752
+ token: session.value,
753
+ id,
754
+ isPendingInvite
755
+ });
756
+ cache.revalidatePath("/team-settings");
757
+ return { success: true };
758
+ }
759
+ var deleteUserAction = traceServerAction("deleteUserAction", deleteUserActionImpl);
760
+ async function fetchServiceAccountsActionImpl(limit = 50, offset = 0, includeRevoked = false) {
761
+ const sessionStore = await headers.cookies();
762
+ const session = sessionStore.get("portal_session");
763
+ if (!session?.value) {
764
+ throw new Error("No session found");
765
+ }
766
+ const result = await fetchServiceAccounts.run({
767
+ token: session.value,
768
+ limit,
769
+ offset,
770
+ includeRevoked
771
+ });
772
+ return {
773
+ serviceAccounts: result.serviceAccounts,
774
+ total: result.total
775
+ };
776
+ }
777
+ var fetchServiceAccountsAction = traceServerAction("fetchServiceAccountsAction", fetchServiceAccountsActionImpl);
778
+ async function createServiceAccountActionImpl2(name) {
779
+ const sessionStore = await headers.cookies();
780
+ const session = sessionStore.get("portal_session");
781
+ if (!session?.value) {
782
+ throw new Error("No session found");
783
+ }
784
+ const result = await createServiceAccount.run({
785
+ token: session.value,
786
+ name
787
+ });
788
+ cache.revalidatePath("/team-settings");
789
+ return {
790
+ serviceAccount: {
791
+ id: result.service_account.id,
792
+ accountName: result.service_account.accountName
793
+ },
794
+ token: result.token
795
+ };
796
+ }
797
+ traceServerAction("createServiceAccountAction", createServiceAccountActionImpl2);
798
+ async function revokeServiceAccountActionImpl(accountId) {
799
+ const sessionStore = await headers.cookies();
800
+ const session = sessionStore.get("portal_session");
801
+ if (!session?.value) {
802
+ throw new Error("No session found");
803
+ }
804
+ await revokeServiceAccount.run({
805
+ token: session.value,
806
+ accountId
807
+ });
808
+ cache.revalidatePath("/team-settings");
809
+ return { success: true };
810
+ }
811
+ var revokeServiceAccountAction = traceServerAction("revokeServiceAccountAction", revokeServiceAccountActionImpl);
812
+ async function rotateServiceAccountTokenActionImpl(accountId) {
813
+ const sessionStore = await headers.cookies();
814
+ const session = sessionStore.get("portal_session");
815
+ if (!session?.value) {
816
+ throw new Error("No session found");
817
+ }
818
+ const result = await rotateServiceAccountToken.run({
819
+ token: session.value,
820
+ accountId
821
+ });
822
+ cache.revalidatePath("/team-settings");
823
+ return result;
824
+ }
825
+ var rotateServiceAccountTokenAction = traceServerAction("rotateServiceAccountTokenAction", rotateServiceAccountTokenActionImpl);
826
+ async function fetchInstancesActionImpl() {
827
+ const sessionStore = await headers.cookies();
828
+ const session = sessionStore.get("portal_session");
829
+ if (!session?.value) {
830
+ throw new Error("No session found");
831
+ }
832
+ const result = await fetchInstances.run({
833
+ token: session.value
834
+ });
835
+ return result.instances;
836
+ }
837
+ var fetchInstancesAction = traceServerAction("fetchInstancesAction", fetchInstancesActionImpl);
838
+ async function fetchSamlConfigActionImpl() {
839
+ const sessionStore = await headers.cookies();
840
+ const session = sessionStore.get("portal_session");
841
+ if (!session?.value) {
842
+ throw new Error("No session found");
843
+ }
844
+ const result = await fetchSamlConfig.run({
845
+ token: session.value
846
+ });
847
+ return result.config;
848
+ }
849
+ var fetchSamlConfigAction = traceServerAction("fetchSamlConfigAction", fetchSamlConfigActionImpl);
850
+ async function updateSamlConfigActionImpl(idpMetadataXml, idpPublicCert) {
851
+ const sessionStore = await headers.cookies();
852
+ const session = sessionStore.get("portal_session");
853
+ if (!session?.value) {
854
+ throw new Error("No session found");
855
+ }
856
+ await updateSamlConfig.run({
857
+ token: session.value,
858
+ idpMetadataXml,
859
+ idpPublicCert
860
+ });
861
+ cache.revalidatePath("/team-settings");
862
+ return { success: true };
863
+ }
864
+ var updateSamlConfigAction = traceServerAction("updateSamlConfigAction", updateSamlConfigActionImpl);
865
+ async function toggleSamlEnabledActionImpl(enabled) {
866
+ const sessionStore = await headers.cookies();
867
+ const session = sessionStore.get("portal_session");
868
+ if (!session?.value) {
869
+ throw new Error("No session found");
870
+ }
871
+ const result = await toggleSamlEnabled.run({
872
+ token: session.value,
873
+ enabled
874
+ });
875
+ cache.revalidatePath("/team-settings");
876
+ return result;
877
+ }
878
+ var toggleSamlEnabledAction = traceServerAction("toggleSamlEnabledAction", toggleSamlEnabledActionImpl);
879
+ async function deprovisionSamlActionImpl() {
880
+ const sessionStore = await headers.cookies();
881
+ const session = sessionStore.get("portal_session");
882
+ if (!session?.value) {
883
+ throw new Error("No session found");
884
+ }
885
+ await deprovisionSaml.run({
886
+ token: session.value
887
+ });
888
+ cache.revalidatePath("/team-settings");
889
+ return { success: true };
890
+ }
891
+ var deprovisionSamlAction = traceServerAction("deprovisionSamlAction", deprovisionSamlActionImpl);
892
+ async function fetchAppFeaturesImpl() {
893
+ const sessionStore = await headers.cookies();
894
+ const session = sessionStore.get("portal_session");
895
+ const appSlug = process.env.PORTAL_APP_SLUG;
896
+ if (!appSlug) {
897
+ throw new Error("PORTAL_APP_SLUG is not configured");
898
+ }
899
+ const params = new URLSearchParams({ app_slug: appSlug });
900
+ if (session?.value) {
901
+ try {
902
+ const payload = decodeJwtPayload(session.value);
903
+ const customerId = payload?.customer_id;
904
+ if (customerId) {
905
+ params.set("customer_id", customerId);
906
+ }
907
+ } catch {
908
+ }
909
+ }
910
+ const url = `${getApiOrigin()}/enterprise-portal/public/app-features?${params.toString()}`;
911
+ const response = await fetch(url, {
912
+ headers: {
913
+ Accept: "application/json"
914
+ }
915
+ });
916
+ if (!response.ok) {
917
+ throw new Error(`Failed to fetch app features: ${response.status} ${response.statusText}`);
918
+ }
919
+ const data = await response.json();
920
+ return {
921
+ epEnabled: data.ep_enabled ?? false,
922
+ trialSignupEnabled: data.trial_signup_enabled ?? false,
923
+ trialExpirationDays: data.trial_expiration_days ?? 30,
924
+ licenseType: data.license_type ?? "trial",
925
+ termsAndConditionsUrl: data.terms_and_conditions_url ?? "",
926
+ epSecurityCenterEnabled: data.ep_security_center_enabled ?? false,
927
+ epSamlAuthEnabled: data.ep_saml_auth_enabled ?? false,
928
+ epHideSupportBundleUploadEnabled: data.ep_hide_support_bundle_upload_enabled ?? false
929
+ };
930
+ }
931
+ var fetchAppFeatures = traceServerAction("fetchAppFeatures", fetchAppFeaturesImpl);
932
+ async function fetchCurrentUserActionImpl() {
933
+ const sessionStore = await headers.cookies();
934
+ const session = sessionStore.get("portal_session");
935
+ if (!session?.value) {
936
+ throw new Error("No session found");
937
+ }
938
+ const result = await fetchCurrentUser.run({ token: session.value });
939
+ return result.user;
940
+ }
941
+ var fetchCurrentUserAction = traceServerAction("fetchCurrentUserAction", fetchCurrentUserActionImpl);
942
+ async function updateUserActionImpl(data) {
943
+ const sessionStore = await headers.cookies();
944
+ const session = sessionStore.get("portal_session");
945
+ if (!session?.value) {
946
+ throw new Error("No session found");
947
+ }
948
+ await updateUser.run({
949
+ token: session.value,
950
+ firstName: data.firstName,
951
+ lastName: data.lastName
952
+ });
953
+ cache.revalidatePath("/user-settings");
954
+ return { success: true };
955
+ }
956
+ var updateUserAction = traceServerAction("updateUserAction", updateUserActionImpl);
957
+ async function fetchNotificationsActionImpl(customerId) {
958
+ const sessionStore = await headers.cookies();
959
+ const session = sessionStore.get("portal_session");
960
+ if (!session?.value) {
961
+ throw new Error("No session found");
962
+ }
963
+ const result = await fetchNotifications.run({
964
+ token: session.value,
965
+ customerId
966
+ });
967
+ return result.notifications;
968
+ }
969
+ var fetchNotificationsAction = traceServerAction("fetchNotificationsAction", fetchNotificationsActionImpl);
970
+ async function updateNotificationsActionImpl(customerId, notifications) {
971
+ const sessionStore = await headers.cookies();
972
+ const session = sessionStore.get("portal_session");
973
+ if (!session?.value) {
974
+ throw new Error("No session found");
975
+ }
976
+ const result = await updateNotifications.run({
977
+ token: session.value,
978
+ customerId,
979
+ notifications
980
+ });
981
+ return result.notifications;
982
+ }
983
+ var updateNotificationsAction = traceServerAction("updateNotificationsAction", updateNotificationsActionImpl);
984
+ async function fetchTeamsForUserSettingsImpl() {
985
+ const sessionStore = await headers.cookies();
986
+ const session = sessionStore.get("portal_session");
987
+ if (!session?.value) {
988
+ return { teams: [], currentCustomerId: void 0 };
989
+ }
990
+ const token = session.value;
991
+ const currentCustomerId = getCustomerIdFromToken(token);
992
+ try {
993
+ const result = await fetchCustomers.run({ token });
994
+ const payload = decodeJwtPayload(token);
995
+ const appId = payload?.app_id || "";
996
+ const appSlug = payload?.app_slug || process.env.PORTAL_APP_SLUG || "";
997
+ const appName = appSlug;
998
+ const teams = result.customers.map((c) => ({
999
+ id: c.id,
1000
+ name: c.name,
1001
+ appId,
1002
+ appName,
1003
+ appSlug
1004
+ }));
1005
+ return { teams, currentCustomerId };
1006
+ } catch (error) {
1007
+ console.error("[fetch-teams-for-user-settings] Failed to fetch teams:", error);
1008
+ return { teams: [], currentCustomerId };
1009
+ }
1010
+ }
1011
+ var fetchTeamsForUserSettings = traceServerAction("fetchTeamsForUserSettings", fetchTeamsForUserSettingsImpl);
1012
+ async function changeTeamActionImpl(customerId) {
1013
+ const sessionStore = await headers.cookies();
1014
+ const session = sessionStore.get("portal_session");
1015
+ if (!session?.value) {
1016
+ throw new Error("No session found");
1017
+ }
1018
+ const result = await switchCustomer.run({
1019
+ token: session.value,
1020
+ customerId
1021
+ });
1022
+ sessionStore.delete("portal_session");
1023
+ sessionStore.set("portal_session", result.token, {
1024
+ httpOnly: true,
1025
+ secure: process.env.NODE_ENV === "production",
1026
+ sameSite: "lax",
1027
+ path: "/"
1028
+ });
1029
+ cache.revalidatePath("/", "layout");
1030
+ }
1031
+ var changeTeamAction = traceServerAction("changeTeamAction", changeTeamActionImpl);
1032
+ async function fetchCustomersForMenuImpl() {
1033
+ try {
1034
+ const sessionStore = await headers.cookies();
1035
+ const session = sessionStore.get("portal_session");
1036
+ if (!session?.value) {
1037
+ return { customers: [] };
1038
+ }
1039
+ const token = session.value;
1040
+ const currentCustomerId = getCustomerIdFromToken(token);
1041
+ const endpoint = `${getApiOrigin()}/enterprise-portal/user`;
1042
+ const response = await authenticatedFetch(endpoint, {
1043
+ method: "GET",
1044
+ token,
1045
+ headers: {
1046
+ Accept: "application/json"
1047
+ }
1048
+ });
1049
+ if (!response.ok) {
1050
+ console.error("[fetch-customers-for-menu] Failed to fetch user data:", response.status);
1051
+ return { customers: [], currentCustomerId };
1052
+ }
1053
+ const payload = await response.json();
1054
+ const userData = payload.data;
1055
+ const mappedCustomers = (userData?.customers || []).map((c) => ({
1056
+ id: c.id,
1057
+ name: c.name
1058
+ }));
1059
+ return {
1060
+ customers: mappedCustomers,
1061
+ currentCustomerId
1062
+ };
1063
+ } catch (error) {
1064
+ if (isRedirectError(error)) {
1065
+ throw error;
1066
+ }
1067
+ console.error("[fetch-customers-for-menu] Failed to fetch customers:", error);
1068
+ return { customers: [] };
1069
+ }
1070
+ }
1071
+ var fetchCustomersForMenu = traceServerAction("fetchCustomersForMenu", fetchCustomersForMenuImpl);
1072
+ async function downloadSupportBundleActionImpl(bundleId) {
1073
+ const sessionStore = await headers.cookies();
1074
+ const session = sessionStore.get("portal_session");
1075
+ if (!session?.value) {
1076
+ return { success: false, error: "Not authenticated" };
1077
+ }
1078
+ try {
1079
+ const result = await downloadSupportBundle.run({
1080
+ token: session.value,
1081
+ bundleId
1082
+ });
1083
+ return { success: true, signedUrl: result.signedUrl };
1084
+ } catch (error) {
1085
+ console.error("[support-bundles] download failed", error);
1086
+ return {
1087
+ success: false,
1088
+ error: error instanceof Error ? error.message : "Failed to download bundle"
1089
+ };
1090
+ }
1091
+ }
1092
+ var downloadSupportBundleAction = traceServerAction("downloadSupportBundleAction", downloadSupportBundleActionImpl);
1093
+ async function deleteSupportBundleActionImpl(bundleId) {
1094
+ const sessionStore = await headers.cookies();
1095
+ const session = sessionStore.get("portal_session");
1096
+ if (!session?.value) {
1097
+ return { success: false, error: "Not authenticated" };
1098
+ }
1099
+ try {
1100
+ await deleteSupportBundle.run({
1101
+ token: session.value,
1102
+ bundleId
1103
+ });
1104
+ return { success: true };
1105
+ } catch (error) {
1106
+ console.error("[support-bundles] delete failed", error);
1107
+ return {
1108
+ success: false,
1109
+ error: error instanceof Error ? error.message : "Failed to delete bundle"
1110
+ };
1111
+ }
1112
+ }
1113
+ var deleteSupportBundleAction = traceServerAction("deleteSupportBundleAction", deleteSupportBundleActionImpl);
1114
+ async function uploadSupportBundleActionImpl(formData) {
1115
+ const sessionStore = await headers.cookies();
1116
+ const session = sessionStore.get("portal_session");
1117
+ if (!session?.value) {
1118
+ return { success: false, error: "Not authenticated" };
1119
+ }
1120
+ const file = formData.get("file");
1121
+ const appId = formData.get("appId");
1122
+ if (!file) {
1123
+ return { success: false, error: "No file provided" };
1124
+ }
1125
+ if (!appId) {
1126
+ return { success: false, error: "No app ID provided" };
1127
+ }
1128
+ const MAX_FILE_SIZE = 500 * 1024 * 1024;
1129
+ if (file.size > MAX_FILE_SIZE) {
1130
+ return { success: false, error: "File size exceeds 500MB limit" };
1131
+ }
1132
+ try {
1133
+ const endpoint = `${getApiOrigin()}/enterprise-portal/support-bundles/upload/${encodeURIComponent(appId)}`;
1134
+ const response = await authenticatedFetch(endpoint, {
1135
+ method: "POST",
1136
+ token: session.value,
1137
+ headers: {
1138
+ "Content-Type": "application/gzip"
1139
+ },
1140
+ body: file,
1141
+ // @ts-ignore - duplex is needed for streaming but not in TypeScript types yet
1142
+ duplex: "half"
1143
+ });
1144
+ if (!response.ok) {
1145
+ const errorText = await response.text().catch(() => "");
1146
+ throw new Error(`Upload failed: ${response.status} ${response.statusText}${errorText ? `: ${errorText}` : ""}`);
1147
+ }
1148
+ const data = await response.json();
1149
+ return {
1150
+ success: true,
1151
+ bundleId: data.bundleId,
1152
+ bundleSlug: data.slug
1153
+ };
1154
+ } catch (error) {
1155
+ console.error("[support-bundles] upload failed", error);
1156
+ return {
1157
+ success: false,
1158
+ error: error instanceof Error ? error.message : "Failed to upload support bundle"
1159
+ };
1160
+ }
1161
+ }
1162
+ var uploadSupportBundleAction = traceServerAction("uploadSupportBundleAction", uploadSupportBundleActionImpl);
1163
+ async function listSupportBundlesActionImpl() {
1164
+ const sessionStore = await headers.cookies();
1165
+ const session = sessionStore.get("portal_session");
1166
+ if (!session?.value) {
1167
+ return { success: false, error: "Not authenticated" };
1168
+ }
1169
+ try {
1170
+ const result = await listSupportBundles.run({
1171
+ token: session.value
1172
+ });
1173
+ return {
1174
+ success: true,
1175
+ bundles: result.bundles,
1176
+ totalCount: result.totalCount
1177
+ };
1178
+ } catch (error) {
1179
+ console.error("[support-bundles] list failed", error);
1180
+ return {
1181
+ success: false,
1182
+ error: error instanceof Error ? error.message : "Failed to list bundles"
1183
+ };
1184
+ }
1185
+ }
1186
+ var listSupportBundlesAction = traceServerAction("listSupportBundlesAction", listSupportBundlesActionImpl);
1187
+ async function fetchUserCore() {
1188
+ const sessionStore = await headers.cookies();
1189
+ const session = sessionStore.get("portal_session");
1190
+ const token = session?.value;
1191
+ if (!token) {
1192
+ return {};
1193
+ }
1194
+ try {
1195
+ const endpoint = `${getApiOrigin()}/enterprise-portal/user`;
1196
+ const response = await authenticatedFetch(endpoint, {
1197
+ method: "GET",
1198
+ token,
1199
+ headers: {
1200
+ Accept: "application/json"
1201
+ }
1202
+ });
1203
+ if (!response.ok) {
1204
+ console.error("[fetch-user] API request failed:", response.status);
1205
+ return {};
1206
+ }
1207
+ const data = await response.json();
1208
+ if (process.env.NODE_ENV !== "production") {
1209
+ console.debug("[fetch-user] user data:", data);
1210
+ }
1211
+ return data;
1212
+ } catch (error) {
1213
+ if (isRedirectError(error)) {
1214
+ throw error;
1215
+ }
1216
+ console.error("[fetch-user] Error fetching from API:", error);
1217
+ return {};
1218
+ }
1219
+ }
1220
+ var fetchUserImpl = traceServerAction("fetchUser", fetchUserCore);
1221
+ var fetchUser = react.cache(fetchUserImpl);
1222
+
60
1223
  // src/actions/index.ts
61
1224
  var getApiOrigin = () => {
62
1225
  return (process.env.REPLICATED_APP_ORIGIN || "https://replicated.app").replace(/\/+$/, "");
@@ -233,11 +1396,15 @@ var fetchCustomBrandingImpl = async () => {
233
1396
  const payload = await response.json();
234
1397
  const brandingObject = {
235
1398
  logo: payload.logoUrl,
236
- title: payload.appName,
237
- customColor1: payload.primaryColor,
238
- customColor2: payload.secondaryColor,
1399
+ title: payload.title,
1400
+ primaryColor: payload.primaryColor,
1401
+ secondaryColor: payload.secondaryColor,
239
1402
  favicon: payload.faviconUrl,
240
- supportPortalLink: payload.supportPortalLink || ""
1403
+ supportPortalLink: payload.supportPortalLink || "",
1404
+ background: payload.background,
1405
+ backgroundImage: payload.backgroundImage,
1406
+ customColor1: payload.customColor1,
1407
+ customColor2: payload.customColor2
241
1408
  };
242
1409
  const brandingData = buffer.Buffer.from(JSON.stringify(brandingObject)).toString("base64");
243
1410
  return {
@@ -500,433 +1667,38 @@ var uploadSupportBundle = defineServerAction({
500
1667
  var getSupportBundleUploadUrl = (appId) => {
501
1668
  return `${getApiOrigin()}/enterprise-portal/support-bundles/upload/${encodeURIComponent(appId)}`;
502
1669
  };
503
- var listReleases = defineServerAction({
504
- id: "releases/list",
505
- description: "Lists available releases for the authenticated customer.",
506
- visibility: "customer",
507
- tags: ["releases"],
508
- async run({ token }, context) {
509
- if (!token || typeof token !== "string") {
510
- throw new Error("List releases requires a session token");
511
- }
512
- const endpoint = `${getApiOrigin()}/enterprise-portal/releases`;
513
- if (process.env.NODE_ENV !== "production") {
514
- console.debug("[portal-components] fetching releases via %s (Enterprise Portal API)", endpoint);
515
- }
516
- const response = await authenticatedFetch(endpoint, {
517
- method: "GET",
518
- token,
519
- headers: {
520
- accept: "application/json"
521
- },
522
- signal: context?.signal
523
- });
524
- const bodyText = await response.text().catch((error) => {
525
- console.warn("[portal-components] listReleases read error", error);
526
- return null;
527
- });
528
- if (!response.ok) {
529
- throw new Error(
530
- `List releases request failed (${response.status} ${response.statusText})`
531
- );
532
- }
533
- return {
534
- status: response.status,
535
- body: bodyText
536
- };
537
- }
538
- });
539
- var asRecord = (value) => {
540
- if (value && typeof value === "object") {
541
- return value;
542
- }
543
- return void 0;
544
- };
545
- var getValue = (record, key) => record ? record[key] : void 0;
546
- var getString = (record, key) => {
547
- const value = getValue(record, key);
548
- return typeof value === "string" ? value : void 0;
549
- };
550
- var getBoolean = (record, key) => {
551
- const value = getValue(record, key);
552
- if (typeof value === "boolean") {
553
- return value;
554
- }
555
- if (typeof value === "number") {
556
- return value === 1;
557
- }
558
- if (typeof value === "string") {
559
- const normalized = value.trim().toLowerCase();
560
- if (["true", "1", "yes"].includes(normalized)) {
561
- return true;
562
- }
563
- if (["false", "0", "no"].includes(normalized)) {
564
- return false;
565
- }
566
- }
567
- return void 0;
568
- };
569
- var toDisplayValue = (value) => {
570
- if (value === null || value === void 0) {
571
- return null;
572
- }
573
- if (typeof value === "string") {
574
- return value;
575
- }
576
- if (typeof value === "number" || typeof value === "boolean") {
577
- return String(value);
578
- }
579
- try {
580
- return JSON.stringify(value);
581
- } catch {
582
- return String(value);
583
- }
584
- };
585
- var normalizeStringArray = (value) => {
586
- if (Array.isArray(value)) {
587
- const normalized = value.map(
588
- (item) => typeof item === "string" ? item.trim() : ""
589
- ).filter((item) => item.length > 0);
590
- return normalized.length ? normalized : void 0;
591
- }
592
- if (typeof value === "string") {
593
- const normalized = value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
594
- return normalized.length ? normalized : void 0;
595
- }
596
- return void 0;
597
- };
598
- var normalizeLicenseFields = (input) => {
599
- if (!input) {
600
- return [];
601
- }
602
- if (Array.isArray(input)) {
603
- return input.map((field, index) => {
604
- if (!field || typeof field !== "object") {
605
- return null;
606
- }
607
- const candidate = field;
608
- const key = typeof candidate.key === "string" && candidate.key.trim().length ? candidate.key.trim() : typeof candidate.name === "string" && candidate.name.trim().length ? candidate.name.trim() : typeof candidate.label === "string" && candidate.label.trim().length ? candidate.label.trim() : `field-${index}`;
609
- const label = typeof candidate.label === "string" && candidate.label.trim().length ? candidate.label.trim() : typeof candidate.name === "string" && candidate.name.trim().length ? candidate.name.trim() : key;
610
- let value = candidate.value ?? candidate.data ?? candidate.content;
611
- if ((value === void 0 || value === null) && typeof candidate.text === "string") {
612
- value = candidate.text;
613
- }
614
- if ((value === void 0 || value === null) && typeof candidate.defaultValue === "string") {
615
- value = candidate.defaultValue;
616
- }
617
- const isSecret = Boolean(
618
- candidate.isSecret ?? candidate.secret ?? candidate.masked
619
- );
620
- const resolved = toDisplayValue(value);
621
- return {
622
- key,
623
- label,
624
- value: resolved,
625
- isSecret
626
- };
627
- }).filter((field) => Boolean(field));
628
- }
629
- if (typeof input === "object") {
630
- return Object.entries(input).map(
631
- ([key, value]) => {
632
- let resolvedValue = value;
633
- let isSecret = false;
634
- if (value && typeof value === "object") {
635
- const obj = value;
636
- if ("value" in obj) {
637
- resolvedValue = obj.value;
638
- }
639
- isSecret = Boolean(obj.isSecret ?? obj.secret ?? obj.masked);
640
- }
641
- const normalized = toDisplayValue(resolvedValue);
642
- return {
643
- key,
644
- label: key,
645
- value: normalized,
646
- isSecret
647
- };
648
- }
649
- );
650
- }
651
- return [];
652
- };
653
- var extractChannelNames = (input) => {
654
- if (!Array.isArray(input)) {
655
- return void 0;
1670
+ async function listReleasesImpl() {
1671
+ const { cookies: cookies9 } = await import('next/headers');
1672
+ const sessionStore = await cookies9();
1673
+ const session = sessionStore.get("portal_session");
1674
+ const token = session?.value;
1675
+ if (!token) {
1676
+ throw new Error("List releases requires a session token");
1677
+ }
1678
+ const endpoint = `${getApiOrigin()}/enterprise-portal/releases`;
1679
+ if (process.env.NODE_ENV !== "production") {
1680
+ console.debug("[portal-components] fetching releases via %s (Enterprise Portal API)", endpoint);
656
1681
  }
657
- const names = input.map((item) => {
658
- if (typeof item === "string") {
659
- return item.trim();
660
- }
661
- const record = asRecord(item);
662
- if (!record) {
663
- return null;
664
- }
665
- return getString(record, "name") ?? getString(record, "channelName") ?? getString(record, "channel") ?? getString(record, "channelSlug") ?? getString(record, "slug") ?? void 0;
666
- }).filter((name) => Boolean(name && name.length));
667
- return names.length ? names : void 0;
668
- };
669
- var normalizeEntitlementFields = (fieldsInput, valuesInput) => {
670
- const valuesMap = /* @__PURE__ */ new Map();
671
- const assignValue = (key, value) => {
672
- if (!key) {
673
- return;
1682
+ const response = await authenticatedFetch(endpoint, {
1683
+ method: "GET",
1684
+ token,
1685
+ headers: {
1686
+ accept: "application/json"
674
1687
  }
675
- valuesMap.set(key, toDisplayValue(value));
676
- };
677
- if (Array.isArray(valuesInput)) {
678
- valuesInput.forEach((item) => {
679
- const record = asRecord(item);
680
- if (!record) {
681
- if (typeof item === "string") {
682
- assignValue(item, item);
683
- }
684
- return;
685
- }
686
- const key = getString(record, "name") ?? getString(record, "field") ?? getString(record, "title") ?? getString(record, "label") ?? getString(record, "slug") ?? (() => {
687
- const idValue = getValue(record, "id");
688
- if (typeof idValue === "string" || typeof idValue === "number") {
689
- return String(idValue);
690
- }
691
- return void 0;
692
- })();
693
- const value = getValue(record, "value") ?? getValue(record, "currentValue") ?? getValue(record, "entitlementValue") ?? getValue(record, "content") ?? getValue(record, "data") ?? getValue(record, "defaultVal") ?? getValue(record, "defaultValue");
694
- assignValue(key, value);
695
- });
696
- } else if (valuesInput && typeof valuesInput === "object") {
697
- Object.entries(valuesInput).forEach(
698
- ([key, value]) => assignValue(key, value)
1688
+ });
1689
+ if (!response.ok) {
1690
+ throw new Error(
1691
+ `List releases request failed (${response.status} ${response.statusText})`
699
1692
  );
700
1693
  }
701
- const normalized = [];
702
- if (Array.isArray(fieldsInput)) {
703
- fieldsInput.forEach((item, index) => {
704
- const record = asRecord(item);
705
- if (!record) {
706
- return;
707
- }
708
- const baseKey = getString(record, "name") ?? getString(record, "field") ?? getString(record, "slug") ?? `entitlement-${index}`;
709
- const key = `entitlement-${baseKey}`;
710
- const label = getString(record, "title") ?? getString(record, "label") ?? baseKey;
711
- const defaultValue = getString(record, "defaultVal") ?? getString(record, "default") ?? getString(record, "defaultValue");
712
- const value = valuesMap.get(baseKey) ?? valuesMap.get(label) ?? defaultValue ?? null;
713
- const isSecret = Boolean(
714
- getBoolean(record, "secret") ?? getBoolean(record, "isSecret") ?? getBoolean(record, "masked")
715
- );
716
- normalized.push({
717
- key,
718
- label,
719
- value,
720
- isSecret
721
- });
722
- });
723
- }
724
- valuesMap.forEach((value, key) => {
725
- const normalizedKey = `entitlement-${key}`;
726
- if (!normalized.some((field) => field.key === normalizedKey)) {
727
- normalized.push({
728
- key: normalizedKey,
729
- label: key,
730
- value
731
- });
732
- }
733
- });
734
- return normalized;
735
- };
736
- var normalizeLicensePayload = (payload) => {
737
- const payloadRecord = asRecord(payload);
738
- const rootRecord = asRecord(getValue(payloadRecord, "license")) ?? asRecord(getValue(payloadRecord, "data")) ?? payloadRecord ?? {};
739
- const sourceRecord = asRecord(getValue(rootRecord, "metadata")) ?? rootRecord;
740
- const customer = asRecord(getValue(rootRecord, "customer")) ?? asRecord(getValue(sourceRecord, "customer")) ?? asRecord(getValue(payloadRecord, "customer")) ?? {};
741
- let releaseChannels = normalizeStringArray(
742
- getValue(rootRecord, "releaseChannels") ?? getValue(sourceRecord, "releaseChannels") ?? getValue(sourceRecord, "channels") ?? getValue(rootRecord, "channels") ?? getValue(sourceRecord, "channel") ?? getValue(rootRecord, "channel")
743
- ) ?? void 0;
744
- if (!releaseChannels) {
745
- releaseChannels = extractChannelNames(getValue(rootRecord, "channels")) ?? extractChannelNames(getValue(sourceRecord, "channels")) ?? void 0;
746
- }
747
- let installMethods = normalizeStringArray(
748
- getValue(rootRecord, "installMethods") ?? getValue(sourceRecord, "installMethods") ?? getValue(sourceRecord, "install_options") ?? getValue(rootRecord, "install_options") ?? getValue(sourceRecord, "installOptions")
749
- ) ?? void 0;
750
- if (!installMethods || installMethods.length === 0) {
751
- const resolved = [];
752
- const flag = (key) => getBoolean(rootRecord, key) ?? getBoolean(sourceRecord, key) ?? false;
753
- if (flag("isKotsInstallEnabled")) {
754
- resolved.push("Replicated KOTS");
755
- }
756
- if (flag("isHelmInstallEnabled")) {
757
- resolved.push("Helm");
758
- }
759
- if (flag("isHelmAirgapEnabled")) {
760
- resolved.push("Helm Airgap");
761
- }
762
- if (flag("isEmbeddedClusterDownloadEnabled") || flag("isEmbeddedClusterMultiNodeEnabled")) {
763
- resolved.push("Embedded Cluster");
764
- }
765
- if (flag("isKurlInstallEnabled")) {
766
- resolved.push("kURL");
767
- }
768
- if (flag("isGitopsSupported")) {
769
- resolved.push("GitOps");
770
- }
771
- if (resolved.length) {
772
- installMethods = Array.from(new Set(resolved));
773
- }
774
- }
775
- const expiresAtSource = getValue(sourceRecord, "expiresAt") ?? getValue(sourceRecord, "expireAt") ?? getValue(sourceRecord, "expire_at") ?? getValue(sourceRecord, "expiration") ?? getValue(sourceRecord, "expirationDate") ?? getValue(sourceRecord, "expires_on") ?? getValue(rootRecord, "expiresAt") ?? getValue(rootRecord, "expireAt") ?? getValue(rootRecord, "expire_at") ?? getValue(rootRecord, "expiration");
776
- const expiresAt = typeof expiresAtSource === "string" && expiresAtSource.trim().length ? expiresAtSource : expiresAtSource === null ? null : void 0;
777
- const baseFields = normalizeLicenseFields(
778
- getValue(rootRecord, "additionalFields") ?? getValue(sourceRecord, "additionalFields") ?? getValue(sourceRecord, "fields") ?? getValue(rootRecord, "fields") ?? getValue(payloadRecord, "fields") ?? getValue(payloadRecord, "additional_fields")
779
- );
780
- const entitlementFields = normalizeEntitlementFields(
781
- getValue(rootRecord, "entitlementFields") ?? getValue(sourceRecord, "entitlementFields"),
782
- getValue(rootRecord, "entitlementValues") ?? getValue(sourceRecord, "entitlementValues")
783
- );
784
- const fields = [
785
- ...baseFields,
786
- ...entitlementFields.filter(
787
- (field) => !baseFields.some((existing) => existing.key === field.key)
788
- )
789
- ];
790
- const statusFromSource = getString(sourceRecord, "status") ?? getString(sourceRecord, "state");
791
- const statusLabelFromSource = getString(sourceRecord, "statusLabel") ?? getString(sourceRecord, "stateLabel");
792
- const expiredFlag = getBoolean(sourceRecord, "isExpired") ?? getBoolean(rootRecord, "isExpired");
793
- const derivedStatus = statusFromSource ?? (typeof expiredFlag === "boolean" ? expiredFlag ? "expired" : "active" : void 0);
794
- const statusLabel = statusLabelFromSource ?? (derivedStatus ? derivedStatus.charAt(0).toUpperCase() + derivedStatus.slice(1) : void 0);
795
- const licenseType = getString(sourceRecord, "licenseType") ?? getString(rootRecord, "licenseType");
796
- const status = derivedStatus;
797
- const license = {
798
- id: getString(rootRecord, "id") ?? getString(sourceRecord, "id") ?? getString(sourceRecord, "licenseId") ?? getString(customer, "licenseId") ?? void 0,
799
- status,
800
- statusLabel,
801
- environment: getString(sourceRecord, "environment") ?? getString(sourceRecord, "tier") ?? licenseType ?? void 0,
802
- expiresAt: expiresAt ?? null,
803
- releaseChannels: releaseChannels ?? [
804
- getString(rootRecord, "channelName") ?? getString(rootRecord, "channel") ?? void 0
805
- ].filter((value) => Boolean(value)),
806
- installMethods,
807
- installNotes: getString(sourceRecord, "installNotes"),
808
- customerName: getString(sourceRecord, "customerName") ?? getString(customer, "name") ?? void 0,
809
- customerId: getString(sourceRecord, "customerId") ?? getString(customer, "id") ?? getString(rootRecord, "customerId") ?? void 0,
810
- customerOrganization: getString(customer, "organization") ?? getString(sourceRecord, "customerOrganization") ?? getString(rootRecord, "customerOrganization") ?? void 0,
811
- fields
1694
+ const envelope = await response.json();
1695
+ const data = envelope.data;
1696
+ return {
1697
+ releases: Array.isArray(data?.releases) ? data.releases : [],
1698
+ totalCount: data?.totalCount || 0
812
1699
  };
813
- return license;
814
- };
815
- var fetchLicenseDetails = defineServerAction({
816
- id: "license/fetch-details",
817
- description: "Fetches the authenticated user's enterprise license details.",
818
- visibility: "customer",
819
- tags: ["license", "entitlements"],
820
- async run({ token }, context) {
821
- if (typeof token !== "string" || token.trim().length === 0) {
822
- throw new Error("fetchLicenseDetails requires a non-empty token");
823
- }
824
- const endpoint = `${getApiOrigin()}/enterprise-portal/license`;
825
- if (process.env.NODE_ENV !== "production") {
826
- console.debug("[portal-components] fetching license via %s (Enterprise Portal API)", endpoint);
827
- }
828
- const response = await authenticatedFetch(endpoint, {
829
- method: "GET",
830
- token,
831
- headers: {
832
- accept: "application/json"
833
- },
834
- signal: context?.signal
835
- });
836
- if (!response.ok) {
837
- throw new Error(
838
- `License request failed (${response.status} ${response.statusText})`
839
- );
840
- }
841
- const payload = await response.json();
842
- const licenseData = payload.data;
843
- const license = normalizeLicensePayload(licenseData);
844
- return {
845
- license,
846
- raw: licenseData ?? null
847
- };
848
- }
849
- });
850
- var fetchInstallOptions = defineServerAction({
851
- id: "license/fetch-install-options",
852
- description: "Fetches install options based on license entitlements.",
853
- visibility: "customer",
854
- tags: ["license", "install"],
855
- async run({ token }, context) {
856
- if (typeof token !== "string" || token.trim().length === 0) {
857
- throw new Error("fetchInstallOptions requires a non-empty token");
858
- }
859
- const endpoint = `${getApiOrigin()}/enterprise-portal/license`;
860
- if (process.env.NODE_ENV !== "production") {
861
- console.debug("[portal-components] fetching install options via %s (Enterprise Portal API)", endpoint);
862
- }
863
- const response = await authenticatedFetch(endpoint, {
864
- method: "GET",
865
- token,
866
- headers: {
867
- accept: "application/json"
868
- },
869
- signal: context?.signal
870
- });
871
- if (!response.ok) {
872
- throw new Error(
873
- `License request failed (${response.status} ${response.statusText})`
874
- );
875
- }
876
- const envelope = await response.json();
877
- const licenseData = envelope.data;
878
- const getBoolean2 = (obj, key) => {
879
- if (obj && typeof obj === "object" && key in obj) {
880
- const val = obj[key];
881
- return val === true || val === "true";
882
- }
883
- return false;
884
- };
885
- const showLinux = getBoolean2(licenseData, "isEmbeddedClusterDownloadEnabled");
886
- const showHelm = getBoolean2(licenseData, "isHelmInstallEnabled");
887
- return {
888
- showLinux,
889
- showHelm
890
- };
891
- }
892
- });
893
- var fetchLicenseSummary = defineServerAction({
894
- id: "license/fetch-summary",
895
- description: "Fetches license summary for the license card.",
896
- visibility: "customer",
897
- tags: ["license"],
898
- async run({ token }, context) {
899
- if (typeof token !== "string" || token.trim().length === 0) {
900
- throw new Error("fetchLicenseSummary requires a non-empty token");
901
- }
902
- const endpoint = `${getApiOrigin()}/enterprise-portal/license`;
903
- if (process.env.NODE_ENV !== "production") {
904
- console.debug("[portal-components] fetching license summary via %s (Enterprise Portal API)", endpoint);
905
- }
906
- const response = await authenticatedFetch(endpoint, {
907
- method: "GET",
908
- token,
909
- headers: {
910
- accept: "application/json"
911
- },
912
- signal: context?.signal
913
- });
914
- if (!response.ok) {
915
- throw new Error(
916
- `License request failed (${response.status} ${response.statusText})`
917
- );
918
- }
919
- const envelope = await response.json();
920
- const licenseData = envelope.data;
921
- const license = normalizeLicensePayload(licenseData);
922
- const type = license.environment || "Unknown";
923
- const expiresAt = license.expiresAt || null;
924
- return {
925
- type,
926
- expiresAt
927
- };
928
- }
929
- });
1700
+ }
1701
+ var listReleases = traceServerAction("listReleases", listReleasesImpl);
930
1702
  var fetchCustomers = defineServerAction({
931
1703
  id: "auth/fetch-customers",
932
1704
  description: "Fetches the list of customers/teams for the authenticated user.",
@@ -1977,47 +2749,77 @@ var refreshInvite = defineServerAction({
1977
2749
  });
1978
2750
 
1979
2751
  exports.acceptInvite = acceptInvite;
2752
+ exports.changeTeamAction = changeTeamAction;
2753
+ exports.createInstallOptionsAction = createInstallOptionsAction;
1980
2754
  exports.createServiceAccount = createServiceAccount;
2755
+ exports.createServiceAccountAction = createServiceAccountAction;
1981
2756
  exports.decodeJwtPayload = decodeJwtPayload;
1982
2757
  exports.defineServerAction = defineServerAction;
1983
2758
  exports.deleteSupportBundle = deleteSupportBundle;
2759
+ exports.deleteSupportBundleAction = deleteSupportBundleAction;
1984
2760
  exports.deleteUser = deleteUser;
2761
+ exports.deleteUserAction = deleteUserAction;
1985
2762
  exports.deprovisionSaml = deprovisionSaml;
2763
+ exports.deprovisionSamlAction = deprovisionSamlAction;
2764
+ exports.discardInstallationAction = discardInstallationAction;
1986
2765
  exports.downloadSecuritySBOM = downloadSecuritySBOM;
1987
2766
  exports.downloadSupportBundle = downloadSupportBundle;
2767
+ exports.downloadSupportBundleAction = downloadSupportBundleAction;
2768
+ exports.fetchAppFeatures = fetchAppFeatures;
2769
+ exports.fetchAppInfo = fetchAppInfo;
2770
+ exports.fetchChannelReleasesAction = fetchChannelReleasesAction;
1988
2771
  exports.fetchCurrentUser = fetchCurrentUser;
2772
+ exports.fetchCurrentUserAction = fetchCurrentUserAction;
1989
2773
  exports.fetchCustomBranding = fetchCustomBranding;
1990
2774
  exports.fetchCustomers = fetchCustomers;
2775
+ exports.fetchCustomersForMenu = fetchCustomersForMenu;
1991
2776
  exports.fetchDashboardComposite = fetchDashboardComposite;
1992
2777
  exports.fetchDashboardInstances = fetchDashboardInstances;
1993
- exports.fetchInstallOptions = fetchInstallOptions;
1994
2778
  exports.fetchInstances = fetchInstances;
1995
- exports.fetchLicenseDetails = fetchLicenseDetails;
1996
- exports.fetchLicenseSummary = fetchLicenseSummary;
2779
+ exports.fetchInstancesAction = fetchInstancesAction;
2780
+ exports.fetchLicense = fetchLicense;
1997
2781
  exports.fetchNotifications = fetchNotifications;
2782
+ exports.fetchNotificationsAction = fetchNotificationsAction;
2783
+ exports.fetchPendingInstallationsAction = fetchPendingInstallationsAction;
1998
2784
  exports.fetchSamlConfig = fetchSamlConfig;
2785
+ exports.fetchSamlConfigAction = fetchSamlConfigAction;
1999
2786
  exports.fetchServiceAccounts = fetchServiceAccounts;
2787
+ exports.fetchServiceAccountsAction = fetchServiceAccountsAction;
2000
2788
  exports.fetchTeamStats = fetchTeamStats;
2001
2789
  exports.fetchTeamUsers = fetchTeamUsers;
2790
+ exports.fetchTeamUsersAction = fetchTeamUsersAction;
2791
+ exports.fetchTeamsForUserSettings = fetchTeamsForUserSettings;
2792
+ exports.fetchUser = fetchUser;
2002
2793
  exports.getApiOrigin = getApiOrigin;
2003
2794
  exports.getCustomerIdFromToken = getCustomerIdFromToken;
2795
+ exports.getInstallOptionsAction = getInstallOptionsAction;
2004
2796
  exports.getSecurityInfo = getSecurityInfo;
2005
2797
  exports.getSecurityInfoDiff = getSecurityInfoDiff;
2006
2798
  exports.getSecurityInfoSBOM = getSecurityInfoSBOM;
2007
2799
  exports.getSupportBundleUploadUrl = getSupportBundleUploadUrl;
2008
2800
  exports.initiateLogin = initiateLogin;
2009
2801
  exports.inviteUser = inviteUser;
2802
+ exports.inviteUserAction = inviteUserAction;
2010
2803
  exports.listReleases = listReleases;
2011
2804
  exports.listSupportBundles = listSupportBundles;
2805
+ exports.listSupportBundlesAction = listSupportBundlesAction;
2012
2806
  exports.refreshInvite = refreshInvite;
2013
2807
  exports.revokeServiceAccount = revokeServiceAccount;
2808
+ exports.revokeServiceAccountAction = revokeServiceAccountAction;
2014
2809
  exports.rotateServiceAccountToken = rotateServiceAccountToken;
2810
+ exports.rotateServiceAccountTokenAction = rotateServiceAccountTokenAction;
2015
2811
  exports.switchCustomer = switchCustomer;
2016
2812
  exports.toggleSamlEnabled = toggleSamlEnabled;
2813
+ exports.toggleSamlEnabledAction = toggleSamlEnabledAction;
2814
+ exports.updateInstallOptionsAction = updateInstallOptionsAction;
2017
2815
  exports.updateNotifications = updateNotifications;
2816
+ exports.updateNotificationsAction = updateNotificationsAction;
2018
2817
  exports.updateSamlConfig = updateSamlConfig;
2818
+ exports.updateSamlConfigAction = updateSamlConfigAction;
2019
2819
  exports.updateUser = updateUser;
2820
+ exports.updateUserAction = updateUserAction;
2020
2821
  exports.uploadSupportBundle = uploadSupportBundle;
2822
+ exports.uploadSupportBundleAction = uploadSupportBundleAction;
2021
2823
  exports.verifyMagicLink = verifyMagicLink;
2022
2824
  //# sourceMappingURL=index.js.map
2023
2825
  //# sourceMappingURL=index.js.map