@replicated/portal-components 0.0.2 → 0.0.3

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 (216) hide show
  1. package/components/metadata/registry.json +83 -2
  2. package/components/metadata/registry.md +27 -2
  3. package/dist/actions/index.d.mts +566 -3
  4. package/dist/actions/index.d.ts +566 -3
  5. package/dist/actions/index.js +1853 -12
  6. package/dist/actions/index.js.map +1 -1
  7. package/dist/airgap-instances.d.mts +26 -0
  8. package/dist/airgap-instances.d.ts +26 -0
  9. package/dist/airgap-instances.js +354 -0
  10. package/dist/airgap-instances.js.map +1 -0
  11. package/dist/error-page.d.mts +14 -0
  12. package/dist/error-page.d.ts +14 -0
  13. package/dist/error-page.js +153 -0
  14. package/dist/error-page.js.map +1 -0
  15. package/dist/error.d.mts +15 -0
  16. package/dist/error.d.ts +15 -0
  17. package/dist/error.js +144 -0
  18. package/dist/error.js.map +1 -0
  19. package/dist/esm/actions/index.js +1816 -13
  20. package/dist/esm/actions/index.js.map +1 -1
  21. package/dist/esm/airgap-instances.js +352 -0
  22. package/dist/esm/airgap-instances.js.map +1 -0
  23. package/dist/esm/error-page.js +151 -0
  24. package/dist/esm/error-page.js.map +1 -0
  25. package/dist/esm/error.js +142 -0
  26. package/dist/esm/error.js.map +1 -0
  27. package/dist/esm/helm-install-wizard.js +1007 -0
  28. package/dist/esm/helm-install-wizard.js.map +1 -0
  29. package/dist/esm/index.js +2232 -155
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/install-actions.js +746 -0
  32. package/dist/esm/install-actions.js.map +1 -0
  33. package/dist/esm/install-card.js +115 -0
  34. package/dist/esm/install-card.js.map +1 -0
  35. package/dist/esm/install-targets.js +48 -0
  36. package/dist/esm/install-targets.js.map +1 -0
  37. package/dist/esm/instance-card.js +197 -0
  38. package/dist/esm/instance-card.js.map +1 -0
  39. package/dist/esm/join-team.js +218 -0
  40. package/dist/esm/join-team.js.map +1 -0
  41. package/dist/esm/license-card.js +131 -0
  42. package/dist/esm/license-card.js.map +1 -0
  43. package/dist/esm/license-details.js +667 -0
  44. package/dist/esm/license-details.js.map +1 -0
  45. package/dist/esm/linux-install-wizard.js +1083 -0
  46. package/dist/esm/linux-install-wizard.js.map +1 -0
  47. package/dist/esm/login.js +261 -0
  48. package/dist/esm/login.js.map +1 -0
  49. package/dist/esm/online-instance-list.js +287 -0
  50. package/dist/esm/online-instance-list.js.map +1 -0
  51. package/dist/esm/pending-installations.js +235 -0
  52. package/dist/esm/pending-installations.js.map +1 -0
  53. package/dist/esm/release-history-panel.js +100 -0
  54. package/dist/esm/release-history-panel.js.map +1 -0
  55. package/dist/esm/release-notes-card.js +23 -0
  56. package/dist/esm/release-notes-card.js.map +1 -0
  57. package/dist/esm/security-card.js +700 -0
  58. package/dist/esm/security-card.js.map +1 -0
  59. package/dist/esm/support-bundle-collection-card.js +170 -0
  60. package/dist/esm/support-bundle-collection-card.js.map +1 -0
  61. package/dist/esm/support-bundles-card.js +306 -0
  62. package/dist/esm/support-bundles-card.js.map +1 -0
  63. package/dist/esm/support-card.js +305 -0
  64. package/dist/esm/support-card.js.map +1 -0
  65. package/dist/esm/team-selection.js +117 -0
  66. package/dist/esm/team-selection.js.map +1 -0
  67. package/dist/esm/team-settings-card.js +78 -0
  68. package/dist/esm/team-settings-card.js.map +1 -0
  69. package/dist/esm/team-settings.js +136 -0
  70. package/dist/esm/team-settings.js.map +1 -0
  71. package/dist/esm/top-nav-user-menu.js +173 -0
  72. package/dist/esm/top-nav-user-menu.js.map +1 -0
  73. package/dist/esm/top-nav.js +398 -0
  74. package/dist/esm/top-nav.js.map +1 -0
  75. package/dist/esm/update-layout.js +405 -0
  76. package/dist/esm/update-layout.js.map +1 -0
  77. package/dist/esm/updates-card.js +85 -0
  78. package/dist/esm/updates-card.js.map +1 -0
  79. package/dist/esm/upload-support-bundle-modal.js +143 -0
  80. package/dist/esm/upload-support-bundle-modal.js.map +1 -0
  81. package/dist/esm/user-settings-card.js +21 -0
  82. package/dist/esm/user-settings-card.js.map +1 -0
  83. package/dist/esm/user-settings.js +368 -0
  84. package/dist/esm/user-settings.js.map +1 -0
  85. package/dist/esm/utils/index.js +170 -0
  86. package/dist/esm/utils/index.js.map +1 -0
  87. package/dist/helm-install-wizard.d.mts +38 -0
  88. package/dist/helm-install-wizard.d.ts +38 -0
  89. package/dist/helm-install-wizard.js +1011 -0
  90. package/dist/helm-install-wizard.js.map +1 -0
  91. package/dist/index.d.mts +11 -27
  92. package/dist/index.d.ts +11 -27
  93. package/dist/index.js +2258 -154
  94. package/dist/index.js.map +1 -1
  95. package/dist/install-B19AaKF_.d.mts +233 -0
  96. package/dist/install-Bi1qJ8Bu.d.ts +233 -0
  97. package/dist/install-actions.d.mts +141 -0
  98. package/dist/install-actions.d.ts +141 -0
  99. package/dist/install-actions.js +765 -0
  100. package/dist/install-actions.js.map +1 -0
  101. package/dist/install-card.d.mts +15 -0
  102. package/dist/install-card.d.ts +15 -0
  103. package/dist/install-card.js +117 -0
  104. package/dist/install-card.js.map +1 -0
  105. package/dist/install-targets.d.mts +19 -0
  106. package/dist/install-targets.d.ts +19 -0
  107. package/dist/install-targets.js +50 -0
  108. package/dist/install-targets.js.map +1 -0
  109. package/dist/instance-card.d.mts +22 -0
  110. package/dist/instance-card.d.ts +22 -0
  111. package/dist/instance-card.js +199 -0
  112. package/dist/instance-card.js.map +1 -0
  113. package/dist/join-team.d.mts +30 -0
  114. package/dist/join-team.d.ts +30 -0
  115. package/dist/join-team.js +220 -0
  116. package/dist/join-team.js.map +1 -0
  117. package/dist/license-card.d.mts +15 -0
  118. package/dist/license-card.d.ts +15 -0
  119. package/dist/license-card.js +133 -0
  120. package/dist/license-card.js.map +1 -0
  121. package/dist/license-details.d.mts +10 -0
  122. package/dist/license-details.d.ts +10 -0
  123. package/dist/license-details.js +669 -0
  124. package/dist/license-details.js.map +1 -0
  125. package/dist/linux-install-wizard.d.mts +66 -0
  126. package/dist/linux-install-wizard.d.ts +66 -0
  127. package/dist/linux-install-wizard.js +1093 -0
  128. package/dist/linux-install-wizard.js.map +1 -0
  129. package/dist/login.d.mts +37 -0
  130. package/dist/login.d.ts +37 -0
  131. package/dist/login.js +263 -0
  132. package/dist/login.js.map +1 -0
  133. package/dist/online-instance-list.d.mts +22 -0
  134. package/dist/online-instance-list.d.ts +22 -0
  135. package/dist/online-instance-list.js +289 -0
  136. package/dist/online-instance-list.js.map +1 -0
  137. package/dist/pending-installations.d.mts +15 -0
  138. package/dist/pending-installations.d.ts +15 -0
  139. package/dist/pending-installations.js +237 -0
  140. package/dist/pending-installations.js.map +1 -0
  141. package/dist/release-history-panel.d.mts +22 -0
  142. package/dist/release-history-panel.d.ts +22 -0
  143. package/dist/release-history-panel.js +102 -0
  144. package/dist/release-history-panel.js.map +1 -0
  145. package/dist/release-notes-card.d.mts +13 -0
  146. package/dist/release-notes-card.d.ts +13 -0
  147. package/dist/release-notes-card.js +25 -0
  148. package/dist/release-notes-card.js.map +1 -0
  149. package/dist/security-card.d.mts +73 -0
  150. package/dist/security-card.d.ts +73 -0
  151. package/dist/security-card.js +702 -0
  152. package/dist/security-card.js.map +1 -0
  153. package/dist/styles.css +1877 -194
  154. package/dist/support-bundle-collection-card.d.mts +20 -0
  155. package/dist/support-bundle-collection-card.d.ts +20 -0
  156. package/dist/support-bundle-collection-card.js +172 -0
  157. package/dist/support-bundle-collection-card.js.map +1 -0
  158. package/dist/support-bundles-card.d.mts +19 -0
  159. package/dist/support-bundles-card.d.ts +19 -0
  160. package/dist/support-bundles-card.js +308 -0
  161. package/dist/support-bundles-card.js.map +1 -0
  162. package/dist/support-card.d.mts +8 -0
  163. package/dist/support-card.d.ts +8 -0
  164. package/dist/support-card.js +307 -0
  165. package/dist/support-card.js.map +1 -0
  166. package/dist/team-selection.d.mts +23 -0
  167. package/dist/team-selection.d.ts +23 -0
  168. package/dist/team-selection.js +119 -0
  169. package/dist/team-selection.js.map +1 -0
  170. package/dist/team-settings-card-Dq1d9b5c.d.mts +14 -0
  171. package/dist/team-settings-card-Dq1d9b5c.d.ts +14 -0
  172. package/dist/team-settings-card.d.mts +2 -0
  173. package/dist/team-settings-card.d.ts +2 -0
  174. package/dist/team-settings-card.js +80 -0
  175. package/dist/team-settings-card.js.map +1 -0
  176. package/dist/team-settings.d.mts +25 -0
  177. package/dist/team-settings.d.ts +25 -0
  178. package/dist/team-settings.js +138 -0
  179. package/dist/team-settings.js.map +1 -0
  180. package/dist/top-nav-0mb1K_H0.d.mts +32 -0
  181. package/dist/top-nav-0mb1K_H0.d.ts +32 -0
  182. package/dist/top-nav-user-menu.d.mts +18 -0
  183. package/dist/top-nav-user-menu.d.ts +18 -0
  184. package/dist/top-nav-user-menu.js +175 -0
  185. package/dist/top-nav-user-menu.js.map +1 -0
  186. package/dist/top-nav.d.mts +3 -0
  187. package/dist/top-nav.d.ts +3 -0
  188. package/dist/top-nav.js +400 -0
  189. package/dist/top-nav.js.map +1 -0
  190. package/dist/update-layout.d.mts +12 -0
  191. package/dist/update-layout.d.ts +12 -0
  192. package/dist/update-layout.js +407 -0
  193. package/dist/update-layout.js.map +1 -0
  194. package/dist/updates-card-BbubBrVR.d.mts +18 -0
  195. package/dist/updates-card-BbubBrVR.d.ts +18 -0
  196. package/dist/updates-card.d.mts +2 -0
  197. package/dist/updates-card.d.ts +2 -0
  198. package/dist/updates-card.js +87 -0
  199. package/dist/updates-card.js.map +1 -0
  200. package/dist/upload-support-bundle-modal.d.mts +19 -0
  201. package/dist/upload-support-bundle-modal.d.ts +19 -0
  202. package/dist/upload-support-bundle-modal.js +145 -0
  203. package/dist/upload-support-bundle-modal.js.map +1 -0
  204. package/dist/user-settings-card.d.mts +8 -0
  205. package/dist/user-settings-card.d.ts +8 -0
  206. package/dist/user-settings-card.js +23 -0
  207. package/dist/user-settings-card.js.map +1 -0
  208. package/dist/user-settings.d.mts +47 -0
  209. package/dist/user-settings.d.ts +47 -0
  210. package/dist/user-settings.js +370 -0
  211. package/dist/user-settings.js.map +1 -0
  212. package/dist/utils/index.d.mts +70 -0
  213. package/dist/utils/index.d.ts +70 -0
  214. package/dist/utils/index.js +177 -0
  215. package/dist/utils/index.js.map +1 -0
  216. package/package.json +163 -3
@@ -0,0 +1,669 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+
6
+ /**
7
+ * Enterprise Portal Components
8
+ * This file is generated by tsup. Do not edit manually.
9
+ */
10
+
11
+
12
+ // src/utils/api-client.ts
13
+ async function authenticatedFetch(url, options = {}) {
14
+ const { token, ...fetchOptions } = options;
15
+ const headers = new Headers(fetchOptions.headers);
16
+ if (token) {
17
+ headers.set("authorization", `Bearer ${token}`);
18
+ }
19
+ const response = await fetch(url, {
20
+ ...fetchOptions,
21
+ headers
22
+ });
23
+ if (response.status === 401) {
24
+ await handle401();
25
+ }
26
+ if (response.status === 502 || response.status === 503 || response.status === 504) {
27
+ await handleServerError(response.status);
28
+ }
29
+ return response;
30
+ }
31
+ async function handle401() {
32
+ const { redirect } = await import('next/navigation');
33
+ return redirect("/?expired=1");
34
+ }
35
+ async function handleServerError(statusCode) {
36
+ const { redirect } = await import('next/navigation');
37
+ let sourceUrl;
38
+ try {
39
+ const { headers } = await import('next/headers');
40
+ const headersList = await headers();
41
+ const referer = headersList.get("referer");
42
+ const host = headersList.get("host");
43
+ const pathname = headersList.get("x-invoke-path") || headersList.get("x-forwarded-path");
44
+ if (referer) {
45
+ sourceUrl = referer;
46
+ } else if (host && pathname) {
47
+ const protocol = headersList.get("x-forwarded-proto") || "https";
48
+ sourceUrl = `${protocol}://${host}${pathname}`;
49
+ }
50
+ } catch (error) {
51
+ console.debug("[portal-components] Could not determine source URL", error);
52
+ }
53
+ const params = new URLSearchParams({ code: String(statusCode) });
54
+ if (sourceUrl) {
55
+ params.set("source", sourceUrl);
56
+ }
57
+ return redirect(`/error?${params.toString()}`);
58
+ }
59
+
60
+ // src/actions/index.ts
61
+ var getApiOrigin = () => {
62
+ return (process.env.REPLICATED_APP_ORIGIN || "https://replicated.app").replace(/\/+$/, "");
63
+ };
64
+ var defineServerAction = (definition) => definition;
65
+ var fetchCustomBrandingImpl = async () => {
66
+ const appSlug = process.env.PORTAL_APP_SLUG;
67
+ if (!appSlug) {
68
+ throw new Error("PORTAL_APP_SLUG is not configured");
69
+ }
70
+ const url = `${getApiOrigin()}/v3/custom-branding?app_slug=${encodeURIComponent(
71
+ appSlug
72
+ )}`;
73
+ if (process.env.NODE_ENV !== "production") {
74
+ console.debug(
75
+ "[portal-components] fetching custom branding via %s",
76
+ url
77
+ );
78
+ }
79
+ const response = await fetch(url, {
80
+ headers: {
81
+ accept: "application/json"
82
+ }
83
+ });
84
+ if (!response.ok) {
85
+ throw new Error(
86
+ `Custom branding request failed (${response.status} ${response.statusText})`
87
+ );
88
+ }
89
+ const payload = await response.json();
90
+ const brandingData = payload?.branding_data;
91
+ if (typeof brandingData !== "string") {
92
+ throw new Error("Custom branding response missing branding_data string");
93
+ }
94
+ return {
95
+ brandingData,
96
+ documentation: payload?.documentation ?? null
97
+ };
98
+ };
99
+ react.cache(fetchCustomBrandingImpl);
100
+ var asRecord = (value) => {
101
+ if (value && typeof value === "object") {
102
+ return value;
103
+ }
104
+ return void 0;
105
+ };
106
+ var getValue = (record, key) => record ? record[key] : void 0;
107
+ var getString = (record, key) => {
108
+ const value = getValue(record, key);
109
+ return typeof value === "string" ? value : void 0;
110
+ };
111
+ var getBoolean = (record, key) => {
112
+ const value = getValue(record, key);
113
+ if (typeof value === "boolean") {
114
+ return value;
115
+ }
116
+ if (typeof value === "number") {
117
+ return value === 1;
118
+ }
119
+ if (typeof value === "string") {
120
+ const normalized = value.trim().toLowerCase();
121
+ if (["true", "1", "yes"].includes(normalized)) {
122
+ return true;
123
+ }
124
+ if (["false", "0", "no"].includes(normalized)) {
125
+ return false;
126
+ }
127
+ }
128
+ return void 0;
129
+ };
130
+ var toDisplayValue = (value) => {
131
+ if (value === null || value === void 0) {
132
+ return null;
133
+ }
134
+ if (typeof value === "string") {
135
+ return value;
136
+ }
137
+ if (typeof value === "number" || typeof value === "boolean") {
138
+ return String(value);
139
+ }
140
+ try {
141
+ return JSON.stringify(value);
142
+ } catch {
143
+ return String(value);
144
+ }
145
+ };
146
+ var normalizeStringArray = (value) => {
147
+ if (Array.isArray(value)) {
148
+ const normalized = value.map(
149
+ (item) => typeof item === "string" ? item.trim() : ""
150
+ ).filter((item) => item.length > 0);
151
+ return normalized.length ? normalized : void 0;
152
+ }
153
+ if (typeof value === "string") {
154
+ const normalized = value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
155
+ return normalized.length ? normalized : void 0;
156
+ }
157
+ return void 0;
158
+ };
159
+ var normalizeLicenseFields = (input) => {
160
+ if (!input) {
161
+ return [];
162
+ }
163
+ if (Array.isArray(input)) {
164
+ return input.map((field, index) => {
165
+ if (!field || typeof field !== "object") {
166
+ return null;
167
+ }
168
+ const candidate = field;
169
+ 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}`;
170
+ 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;
171
+ let value = candidate.value ?? candidate.data ?? candidate.content;
172
+ if ((value === void 0 || value === null) && typeof candidate.text === "string") {
173
+ value = candidate.text;
174
+ }
175
+ if ((value === void 0 || value === null) && typeof candidate.defaultValue === "string") {
176
+ value = candidate.defaultValue;
177
+ }
178
+ const isSecret = Boolean(
179
+ candidate.isSecret ?? candidate.secret ?? candidate.masked
180
+ );
181
+ const resolved = toDisplayValue(value);
182
+ return {
183
+ key,
184
+ label,
185
+ value: resolved,
186
+ isSecret
187
+ };
188
+ }).filter((field) => Boolean(field));
189
+ }
190
+ if (typeof input === "object") {
191
+ return Object.entries(input).map(
192
+ ([key, value]) => {
193
+ let resolvedValue = value;
194
+ let isSecret = false;
195
+ if (value && typeof value === "object") {
196
+ const obj = value;
197
+ if ("value" in obj) {
198
+ resolvedValue = obj.value;
199
+ }
200
+ isSecret = Boolean(obj.isSecret ?? obj.secret ?? obj.masked);
201
+ }
202
+ const normalized = toDisplayValue(resolvedValue);
203
+ return {
204
+ key,
205
+ label: key,
206
+ value: normalized,
207
+ isSecret
208
+ };
209
+ }
210
+ );
211
+ }
212
+ return [];
213
+ };
214
+ var extractChannelNames = (input) => {
215
+ if (!Array.isArray(input)) {
216
+ return void 0;
217
+ }
218
+ const names = input.map((item) => {
219
+ if (typeof item === "string") {
220
+ return item.trim();
221
+ }
222
+ const record = asRecord(item);
223
+ if (!record) {
224
+ return null;
225
+ }
226
+ return getString(record, "name") ?? getString(record, "channelName") ?? getString(record, "channel") ?? getString(record, "channelSlug") ?? getString(record, "slug") ?? void 0;
227
+ }).filter((name) => Boolean(name && name.length));
228
+ return names.length ? names : void 0;
229
+ };
230
+ var normalizeEntitlementFields = (fieldsInput, valuesInput) => {
231
+ const valuesMap = /* @__PURE__ */ new Map();
232
+ const assignValue = (key, value) => {
233
+ if (!key) {
234
+ return;
235
+ }
236
+ valuesMap.set(key, toDisplayValue(value));
237
+ };
238
+ if (Array.isArray(valuesInput)) {
239
+ valuesInput.forEach((item) => {
240
+ const record = asRecord(item);
241
+ if (!record) {
242
+ if (typeof item === "string") {
243
+ assignValue(item, item);
244
+ }
245
+ return;
246
+ }
247
+ const key = getString(record, "name") ?? getString(record, "field") ?? getString(record, "title") ?? getString(record, "label") ?? getString(record, "slug") ?? (() => {
248
+ const idValue = getValue(record, "id");
249
+ if (typeof idValue === "string" || typeof idValue === "number") {
250
+ return String(idValue);
251
+ }
252
+ return void 0;
253
+ })();
254
+ const value = getValue(record, "value") ?? getValue(record, "currentValue") ?? getValue(record, "entitlementValue") ?? getValue(record, "content") ?? getValue(record, "data") ?? getValue(record, "defaultVal") ?? getValue(record, "defaultValue");
255
+ assignValue(key, value);
256
+ });
257
+ } else if (valuesInput && typeof valuesInput === "object") {
258
+ Object.entries(valuesInput).forEach(
259
+ ([key, value]) => assignValue(key, value)
260
+ );
261
+ }
262
+ const normalized = [];
263
+ if (Array.isArray(fieldsInput)) {
264
+ fieldsInput.forEach((item, index) => {
265
+ const record = asRecord(item);
266
+ if (!record) {
267
+ return;
268
+ }
269
+ const baseKey = getString(record, "name") ?? getString(record, "field") ?? getString(record, "slug") ?? `entitlement-${index}`;
270
+ const key = `entitlement-${baseKey}`;
271
+ const label = getString(record, "title") ?? getString(record, "label") ?? baseKey;
272
+ const defaultValue = getString(record, "defaultVal") ?? getString(record, "default") ?? getString(record, "defaultValue");
273
+ const value = valuesMap.get(baseKey) ?? valuesMap.get(label) ?? defaultValue ?? null;
274
+ const isSecret = Boolean(
275
+ getBoolean(record, "secret") ?? getBoolean(record, "isSecret") ?? getBoolean(record, "masked")
276
+ );
277
+ normalized.push({
278
+ key,
279
+ label,
280
+ value,
281
+ isSecret
282
+ });
283
+ });
284
+ }
285
+ valuesMap.forEach((value, key) => {
286
+ const normalizedKey = `entitlement-${key}`;
287
+ if (!normalized.some((field) => field.key === normalizedKey)) {
288
+ normalized.push({
289
+ key: normalizedKey,
290
+ label: key,
291
+ value
292
+ });
293
+ }
294
+ });
295
+ return normalized;
296
+ };
297
+ var normalizeLicensePayload = (payload) => {
298
+ const payloadRecord = asRecord(payload);
299
+ const rootRecord = asRecord(getValue(payloadRecord, "license")) ?? asRecord(getValue(payloadRecord, "data")) ?? payloadRecord ?? {};
300
+ const sourceRecord = asRecord(getValue(rootRecord, "metadata")) ?? rootRecord;
301
+ const customer = asRecord(getValue(rootRecord, "customer")) ?? asRecord(getValue(sourceRecord, "customer")) ?? asRecord(getValue(payloadRecord, "customer")) ?? {};
302
+ let releaseChannels = normalizeStringArray(
303
+ getValue(rootRecord, "releaseChannels") ?? getValue(sourceRecord, "releaseChannels") ?? getValue(sourceRecord, "channels") ?? getValue(rootRecord, "channels") ?? getValue(sourceRecord, "channel") ?? getValue(rootRecord, "channel")
304
+ ) ?? void 0;
305
+ if (!releaseChannels) {
306
+ releaseChannels = extractChannelNames(getValue(rootRecord, "channels")) ?? extractChannelNames(getValue(sourceRecord, "channels")) ?? void 0;
307
+ }
308
+ let installMethods = normalizeStringArray(
309
+ getValue(rootRecord, "installMethods") ?? getValue(sourceRecord, "installMethods") ?? getValue(sourceRecord, "install_options") ?? getValue(rootRecord, "install_options") ?? getValue(sourceRecord, "installOptions")
310
+ ) ?? void 0;
311
+ if (!installMethods || installMethods.length === 0) {
312
+ const resolved = [];
313
+ const flag = (key) => getBoolean(rootRecord, key) ?? getBoolean(sourceRecord, key) ?? false;
314
+ if (flag("isKotsInstallEnabled")) {
315
+ resolved.push("Replicated KOTS");
316
+ }
317
+ if (flag("isHelmInstallEnabled")) {
318
+ resolved.push("Helm");
319
+ }
320
+ if (flag("isHelmAirgapEnabled")) {
321
+ resolved.push("Helm Airgap");
322
+ }
323
+ if (flag("isEmbeddedClusterDownloadEnabled") || flag("isEmbeddedClusterMultiNodeEnabled")) {
324
+ resolved.push("Embedded Cluster");
325
+ }
326
+ if (flag("isKurlInstallEnabled")) {
327
+ resolved.push("kURL");
328
+ }
329
+ if (flag("isGitopsSupported")) {
330
+ resolved.push("GitOps");
331
+ }
332
+ if (resolved.length) {
333
+ installMethods = Array.from(new Set(resolved));
334
+ }
335
+ }
336
+ 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");
337
+ const expiresAt = typeof expiresAtSource === "string" && expiresAtSource.trim().length ? expiresAtSource : expiresAtSource === null ? null : void 0;
338
+ const baseFields = normalizeLicenseFields(
339
+ getValue(rootRecord, "additionalFields") ?? getValue(sourceRecord, "additionalFields") ?? getValue(sourceRecord, "fields") ?? getValue(rootRecord, "fields") ?? getValue(payloadRecord, "fields") ?? getValue(payloadRecord, "additional_fields")
340
+ );
341
+ const entitlementFields = normalizeEntitlementFields(
342
+ getValue(rootRecord, "entitlementFields") ?? getValue(sourceRecord, "entitlementFields"),
343
+ getValue(rootRecord, "entitlementValues") ?? getValue(sourceRecord, "entitlementValues")
344
+ );
345
+ const fields = [
346
+ ...baseFields,
347
+ ...entitlementFields.filter(
348
+ (field) => !baseFields.some((existing) => existing.key === field.key)
349
+ )
350
+ ];
351
+ const statusFromSource = getString(sourceRecord, "status") ?? getString(sourceRecord, "state");
352
+ const statusLabelFromSource = getString(sourceRecord, "statusLabel") ?? getString(sourceRecord, "stateLabel");
353
+ const expiredFlag = getBoolean(sourceRecord, "isExpired") ?? getBoolean(rootRecord, "isExpired");
354
+ const derivedStatus = statusFromSource ?? (typeof expiredFlag === "boolean" ? expiredFlag ? "expired" : "active" : void 0);
355
+ const statusLabel = statusLabelFromSource ?? (derivedStatus ? derivedStatus.charAt(0).toUpperCase() + derivedStatus.slice(1) : void 0);
356
+ const licenseType = getString(sourceRecord, "licenseType") ?? getString(rootRecord, "licenseType");
357
+ const status = derivedStatus;
358
+ const license = {
359
+ id: getString(rootRecord, "id") ?? getString(sourceRecord, "id") ?? getString(sourceRecord, "licenseId") ?? getString(customer, "licenseId") ?? void 0,
360
+ status,
361
+ statusLabel,
362
+ environment: getString(sourceRecord, "environment") ?? getString(sourceRecord, "tier") ?? licenseType ?? void 0,
363
+ expiresAt: expiresAt ?? null,
364
+ releaseChannels: releaseChannels ?? [
365
+ getString(rootRecord, "channelName") ?? getString(rootRecord, "channel") ?? void 0
366
+ ].filter((value) => Boolean(value)),
367
+ installMethods,
368
+ installNotes: getString(sourceRecord, "installNotes"),
369
+ customerName: getString(sourceRecord, "customerName") ?? getString(customer, "name") ?? void 0,
370
+ customerId: getString(sourceRecord, "customerId") ?? getString(customer, "id") ?? getString(rootRecord, "customerId") ?? void 0,
371
+ customerOrganization: getString(customer, "organization") ?? getString(sourceRecord, "customerOrganization") ?? getString(rootRecord, "customerOrganization") ?? void 0,
372
+ fields
373
+ };
374
+ return license;
375
+ };
376
+ var fetchLicenseDetails = defineServerAction({
377
+ id: "license/fetch-details",
378
+ description: "Fetches the authenticated user's enterprise license details.",
379
+ visibility: "customer",
380
+ tags: ["license", "entitlements"],
381
+ async run({ token }, context) {
382
+ if (typeof token !== "string" || token.trim().length === 0) {
383
+ throw new Error("fetchLicenseDetails requires a non-empty token");
384
+ }
385
+ const endpoint = `${getApiOrigin()}/v3/license`;
386
+ const response = await authenticatedFetch(endpoint, {
387
+ method: "GET",
388
+ token,
389
+ headers: {
390
+ accept: "application/json"
391
+ },
392
+ signal: context?.signal
393
+ });
394
+ if (!response.ok) {
395
+ throw new Error(
396
+ `License request failed (${response.status} ${response.statusText})`
397
+ );
398
+ }
399
+ const payload = await response.json();
400
+ const license = normalizeLicensePayload(payload);
401
+ return {
402
+ license,
403
+ raw: payload ?? null
404
+ };
405
+ }
406
+ });
407
+ var ShieldIcon = (props) => /* @__PURE__ */ jsxRuntime.jsx(
408
+ "svg",
409
+ {
410
+ xmlns: "http://www.w3.org/2000/svg",
411
+ viewBox: "0 0 24 24",
412
+ fill: "none",
413
+ stroke: "currentColor",
414
+ strokeWidth: 2,
415
+ strokeLinecap: "round",
416
+ strokeLinejoin: "round",
417
+ "aria-hidden": "true",
418
+ ...props,
419
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" })
420
+ }
421
+ );
422
+ var CalendarIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
423
+ "svg",
424
+ {
425
+ xmlns: "http://www.w3.org/2000/svg",
426
+ viewBox: "0 0 24 24",
427
+ fill: "none",
428
+ stroke: "currentColor",
429
+ strokeWidth: 2,
430
+ strokeLinecap: "round",
431
+ strokeLinejoin: "round",
432
+ "aria-hidden": "true",
433
+ ...props,
434
+ children: [
435
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 2v4" }),
436
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 2v4" }),
437
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: 18, height: 18, x: 3, y: 4, rx: 2 }),
438
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 10h18" })
439
+ ]
440
+ }
441
+ );
442
+ var DownloadIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
443
+ "svg",
444
+ {
445
+ xmlns: "http://www.w3.org/2000/svg",
446
+ viewBox: "0 0 24 24",
447
+ fill: "none",
448
+ stroke: "currentColor",
449
+ strokeWidth: 2,
450
+ strokeLinecap: "round",
451
+ strokeLinejoin: "round",
452
+ "aria-hidden": "true",
453
+ ...props,
454
+ children: [
455
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 17V3" }),
456
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 11 6 6 6-6" }),
457
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 21H5" })
458
+ ]
459
+ }
460
+ );
461
+ var BuildingIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
462
+ "svg",
463
+ {
464
+ xmlns: "http://www.w3.org/2000/svg",
465
+ viewBox: "0 0 24 24",
466
+ fill: "none",
467
+ stroke: "currentColor",
468
+ strokeWidth: 2,
469
+ strokeLinecap: "round",
470
+ strokeLinejoin: "round",
471
+ "aria-hidden": "true",
472
+ ...props,
473
+ children: [
474
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: 16, height: 20, x: 4, y: 2, rx: 2, ry: 2 }),
475
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 22v-4h6v4" }),
476
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 6h.01" }),
477
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 6h.01" }),
478
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 6h.01" }),
479
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 10h.01" }),
480
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 14h.01" }),
481
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 10h.01" }),
482
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 14h.01" }),
483
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 10h.01" }),
484
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 14h.01" })
485
+ ]
486
+ }
487
+ );
488
+ var CheckIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
489
+ "svg",
490
+ {
491
+ xmlns: "http://www.w3.org/2000/svg",
492
+ viewBox: "0 0 24 24",
493
+ fill: "none",
494
+ stroke: "currentColor",
495
+ strokeWidth: 2,
496
+ strokeLinecap: "round",
497
+ strokeLinejoin: "round",
498
+ "aria-hidden": "true",
499
+ ...props,
500
+ children: [
501
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21.8 10A10 10 0 1 1 17 3.33" }),
502
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 11 3 3L22 4" })
503
+ ]
504
+ }
505
+ );
506
+ var formatExpiration = (value) => {
507
+ if (!value || value === "never") {
508
+ return "Does not expire";
509
+ }
510
+ const date = new Date(value);
511
+ if (Number.isNaN(date.getTime())) {
512
+ return value;
513
+ }
514
+ return date.toLocaleDateString(void 0, {
515
+ year: "numeric",
516
+ month: "short",
517
+ day: "numeric"
518
+ });
519
+ };
520
+ var maskValue = (value, isSecret) => {
521
+ if (isSecret) {
522
+ return "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
523
+ }
524
+ if (typeof value === "string" && value.trim().length > 0) {
525
+ return value;
526
+ }
527
+ return "No value set";
528
+ };
529
+ var getFieldTextClass = (value) => {
530
+ if (value === "does-not-expire") {
531
+ return "text-gray-500";
532
+ }
533
+ return value && value.trim().length > 0 ? "text-gray-500" : "text-gray-300";
534
+ };
535
+ var InfoRow = ({
536
+ icon,
537
+ title,
538
+ children
539
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-3", children: [
540
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-gray-900", children: icon }),
541
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
542
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-medium text-gray-900", children: title }),
543
+ children
544
+ ] })
545
+ ] });
546
+ var renderInstallOrChannel = (values) => {
547
+ if (!values || values.length === 0) {
548
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Not specified" });
549
+ }
550
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500", children: values.join(", ") });
551
+ };
552
+ var buildPrimaryRows = (license) => {
553
+ const rows = [];
554
+ rows.push({
555
+ key: "status",
556
+ node: /* @__PURE__ */ jsxRuntime.jsxs(
557
+ InfoRow,
558
+ {
559
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ShieldIcon, { className: "h-5 w-5" }),
560
+ title: "License Status",
561
+ children: [
562
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex items-center text-sm text-gray-600", children: [
563
+ /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "mr-1.5 h-4 w-4 text-green-500" }),
564
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: license.statusLabel ?? (license.status ? license.status.charAt(0).toUpperCase() + license.status.slice(1) : "Unknown") })
565
+ ] }),
566
+ license.environment ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500", children: license.environment }) : null
567
+ ]
568
+ }
569
+ )
570
+ });
571
+ rows.push({
572
+ key: "expiration",
573
+ node: /* @__PURE__ */ jsxRuntime.jsx(
574
+ InfoRow,
575
+ {
576
+ icon: /* @__PURE__ */ jsxRuntime.jsx(CalendarIcon, { className: "h-5 w-5" }),
577
+ title: "Expiration Date",
578
+ children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500", children: formatExpiration(license.expiresAt) })
579
+ }
580
+ )
581
+ });
582
+ rows.push({
583
+ key: "channels",
584
+ node: /* @__PURE__ */ jsxRuntime.jsx(
585
+ InfoRow,
586
+ {
587
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ShieldIcon, { className: "h-5 w-5" }),
588
+ title: "Release Channel(s)",
589
+ children: renderInstallOrChannel(license.releaseChannels)
590
+ }
591
+ )
592
+ });
593
+ rows.push({
594
+ key: "installs",
595
+ node: /* @__PURE__ */ jsxRuntime.jsx(
596
+ InfoRow,
597
+ {
598
+ icon: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, { className: "h-5 w-5" }),
599
+ title: "Install Options",
600
+ children: renderInstallOrChannel(license.installMethods)
601
+ }
602
+ )
603
+ });
604
+ rows.push({
605
+ key: "customer",
606
+ node: /* @__PURE__ */ jsxRuntime.jsxs(
607
+ InfoRow,
608
+ {
609
+ icon: /* @__PURE__ */ jsxRuntime.jsx(BuildingIcon, { className: "h-5 w-5" }),
610
+ title: "Customer Name",
611
+ children: [
612
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-gray-500", children: license.customerName ?? "Unknown customer" }),
613
+ license.customerId ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-400", children: [
614
+ "Customer ID: ",
615
+ license.customerId
616
+ ] }) : null
617
+ ]
618
+ }
619
+ )
620
+ });
621
+ return rows;
622
+ };
623
+ var renderFields = (fields) => {
624
+ if (!fields.length) {
625
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "No additional fields available." });
626
+ }
627
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3", children: fields.map((field) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
628
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-900", children: field.label }),
629
+ /* @__PURE__ */ jsxRuntime.jsx(
630
+ "p",
631
+ {
632
+ className: `mt-1 break-words text-sm ${getFieldTextClass(
633
+ field.value
634
+ )}`,
635
+ children: maskValue(field.value, field.isSecret)
636
+ }
637
+ )
638
+ ] }, field.key)) });
639
+ };
640
+ var LicenseDetails = async ({
641
+ token,
642
+ title = "License Details",
643
+ description = "View your enterprise license details"
644
+ }) => {
645
+ if (typeof token !== "string" || token.trim().length === 0) {
646
+ throw new Error("LicenseDetails component requires a non-empty token");
647
+ }
648
+ const response = await fetchLicenseDetails.run({ token });
649
+ console.debug("[portal-components] license response", response.raw);
650
+ const { license } = response;
651
+ const rows = buildPrimaryRows(license);
652
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-3xl border border-gray-100 bg-white p-8 shadow-[0_18px_45px_rgba(17,24,39,0.08)]", children: [
653
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col border-b border-gray-100 pb-6", children: [
654
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-3xl font-bold text-gray-900", children: title }),
655
+ description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-gray-600", children: description }) : null
656
+ ] }),
657
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 space-y-6", children: [
658
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-gray-100 bg-white p-6 sm:p-8", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3", children: rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: row.node }, row.key)) }) }),
659
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-gray-100 bg-white p-6 sm:p-8", children: [
660
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "mb-4 text-lg font-medium text-gray-900", children: "Additional License Fields" }),
661
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: renderFields(license.fields ?? []) })
662
+ ] })
663
+ ] })
664
+ ] });
665
+ };
666
+
667
+ exports.LicenseDetails = LicenseDetails;
668
+ //# sourceMappingURL=license-details.js.map
669
+ //# sourceMappingURL=license-details.js.map