@replicated/portal-components 0.0.17 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/metadata/registry.json +2 -2
- package/components/metadata/registry.md +2 -2
- package/dist/actions/change-team.d.mts +10 -0
- package/dist/actions/change-team.d.ts +10 -0
- package/dist/actions/change-team.js +399 -0
- package/dist/actions/change-team.js.map +1 -0
- package/dist/actions/index.d.mts +2 -1
- package/dist/actions/index.d.ts +2 -1
- package/dist/actions/index.js +1085 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/install-actions.d.mts +2 -0
- package/dist/actions/install-actions.d.ts +2 -0
- package/dist/actions/install-actions.js +627 -0
- package/dist/actions/install-actions.js.map +1 -0
- package/dist/actions/service-account.d.mts +2 -0
- package/dist/actions/service-account.d.ts +2 -0
- package/dist/actions/service-account.js +320 -0
- package/dist/actions/service-account.js.map +1 -0
- package/dist/actions/support-bundles.d.mts +2 -0
- package/dist/actions/support-bundles.d.ts +2 -0
- package/dist/actions/support-bundles.js +606 -0
- package/dist/actions/support-bundles.js.map +1 -0
- package/dist/actions/team-settings.d.mts +2 -0
- package/dist/actions/team-settings.d.ts +2 -0
- package/dist/actions/team-settings.js +976 -0
- package/dist/actions/team-settings.js.map +1 -0
- package/dist/actions/user-settings.d.mts +2 -0
- package/dist/actions/user-settings.d.ts +2 -0
- package/dist/actions/user-settings.js +568 -0
- package/dist/actions/user-settings.js.map +1 -0
- package/dist/airgap-instances.d.mts +2 -1
- package/dist/airgap-instances.d.ts +2 -1
- package/dist/airgap-instances.js +232 -16
- package/dist/airgap-instances.js.map +1 -1
- package/dist/esm/actions/change-team.js +396 -0
- package/dist/esm/actions/change-team.js.map +1 -0
- package/dist/esm/actions/index.js +1054 -1
- package/dist/esm/actions/index.js.map +1 -1
- package/dist/esm/actions/install-actions.js +620 -0
- package/dist/esm/actions/install-actions.js.map +1 -0
- package/dist/esm/actions/service-account.js +318 -0
- package/dist/esm/actions/service-account.js.map +1 -0
- package/dist/esm/actions/support-bundles.js +601 -0
- package/dist/esm/actions/support-bundles.js.map +1 -0
- package/dist/esm/actions/team-settings.js +962 -0
- package/dist/esm/actions/team-settings.js.map +1 -0
- package/dist/esm/actions/user-settings.js +562 -0
- package/dist/esm/actions/user-settings.js.map +1 -0
- package/dist/esm/airgap-instances.js +232 -16
- package/dist/esm/airgap-instances.js.map +1 -1
- package/dist/esm/helm-install-wizard.js +9 -2
- package/dist/esm/helm-install-wizard.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/install-actions.js.map +1 -1
- package/dist/esm/instance-card.js +232 -16
- package/dist/esm/instance-card.js.map +1 -1
- package/dist/esm/license-details.js.map +1 -1
- package/dist/esm/linux-install-wizard.js +128 -96
- package/dist/esm/linux-install-wizard.js.map +1 -1
- package/dist/esm/online-instance-list.js +232 -16
- package/dist/esm/online-instance-list.js.map +1 -1
- package/dist/esm/pending-installations.js +4 -3
- package/dist/esm/pending-installations.js.map +1 -1
- package/dist/esm/support-bundle-collection-card.js +10 -4
- package/dist/esm/support-bundle-collection-card.js.map +1 -1
- package/dist/esm/support-bundles-card.js +1 -1
- package/dist/esm/support-bundles-card.js.map +1 -1
- package/dist/esm/support-card.js.map +1 -1
- package/dist/esm/top-nav.js.map +1 -1
- package/dist/esm/update-layout.js.map +1 -1
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/helm-install-wizard.d.mts +3 -2
- package/dist/helm-install-wizard.d.ts +3 -2
- package/dist/helm-install-wizard.js +9 -2
- package/dist/helm-install-wizard.js.map +1 -1
- package/dist/{index-DkjaogsF.d.ts → index-BAiVrSSR.d.mts} +148 -1
- package/dist/{index-DkjaogsF.d.mts → index-DWt-N5od.d.ts} +148 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/install-actions.d.mts +3 -2
- package/dist/install-actions.d.ts +3 -2
- package/dist/install-actions.js.map +1 -1
- package/dist/install-card.d.mts +2 -1
- package/dist/install-card.d.ts +2 -1
- package/dist/instance-card.d.mts +2 -1
- package/dist/instance-card.d.ts +2 -1
- package/dist/instance-card.js +232 -16
- package/dist/instance-card.js.map +1 -1
- package/dist/license-card.d.mts +2 -1
- package/dist/license-card.d.ts +2 -1
- package/dist/license-details.js.map +1 -1
- package/dist/linux-install-wizard.d.mts +6 -6
- package/dist/linux-install-wizard.d.ts +6 -6
- package/dist/linux-install-wizard.js +128 -96
- package/dist/linux-install-wizard.js.map +1 -1
- package/dist/online-instance-list.d.mts +2 -1
- package/dist/online-instance-list.d.ts +2 -1
- package/dist/online-instance-list.js +232 -16
- package/dist/online-instance-list.js.map +1 -1
- package/dist/pending-installations.d.mts +6 -3
- package/dist/pending-installations.d.ts +6 -3
- package/dist/pending-installations.js +4 -3
- package/dist/pending-installations.js.map +1 -1
- package/dist/security-card.d.mts +2 -1
- package/dist/security-card.d.ts +2 -1
- package/dist/styles.css +9 -20
- package/dist/support-bundle-collection-card.js +9 -3
- package/dist/support-bundle-collection-card.js.map +1 -1
- package/dist/support-bundles-card.d.mts +2 -1
- package/dist/support-bundles-card.d.ts +2 -1
- package/dist/support-bundles-card.js +1 -1
- package/dist/support-bundles-card.js.map +1 -1
- package/dist/support-card.js.map +1 -1
- package/dist/top-nav.js.map +1 -1
- package/dist/update-layout.js.map +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +32 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { bp as ActionResult, br as ListBundlesResult, bq as UploadSupportBundleResult, bt as deleteSupportBundleAction, bs as downloadSupportBundleAction, bv as listSupportBundlesAction, bu as uploadSupportBundleAction } from '../index-DWt-N5od.js';
|
|
2
|
+
import './change-team.js';
|
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var headers = require('next/headers');
|
|
5
|
+
var buffer = require('buffer');
|
|
6
|
+
var react = require('react');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Enterprise Portal Components
|
|
10
|
+
* This file is generated by tsup. Do not edit manually.
|
|
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);
|
|
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
|
+
});
|
|
121
|
+
|
|
122
|
+
// src/utils/observability/tracing.ts
|
|
123
|
+
var tracerCache = void 0;
|
|
124
|
+
function getTracer() {
|
|
125
|
+
if (tracerCache !== void 0) {
|
|
126
|
+
return tracerCache;
|
|
127
|
+
}
|
|
128
|
+
const rawFlag2 = String(process.env.USE_DATADOG_APM || "").toLowerCase();
|
|
129
|
+
const isEnabled2 = rawFlag2 === "true";
|
|
130
|
+
if (!isEnabled2) {
|
|
131
|
+
tracerCache = null;
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
const tracerModule = (init_tracer(), __toCommonJS(tracer_exports));
|
|
136
|
+
const tracer2 = tracerModule.default || tracerModule;
|
|
137
|
+
if (tracer2 && typeof tracer2.trace === "function") {
|
|
138
|
+
tracerCache = tracer2;
|
|
139
|
+
return tracerCache;
|
|
140
|
+
}
|
|
141
|
+
} catch (err) {
|
|
142
|
+
console.warn("Failed to load tracer:", err);
|
|
143
|
+
}
|
|
144
|
+
tracerCache = null;
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
async function withTrace(name, fn) {
|
|
148
|
+
const activeTracer = getTracer();
|
|
149
|
+
if (!activeTracer) {
|
|
150
|
+
return fn(void 0);
|
|
151
|
+
}
|
|
152
|
+
return activeTracer.trace(name, async (span) => {
|
|
153
|
+
if (span) {
|
|
154
|
+
span.setTag("component", "application");
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
const result = await fn(span);
|
|
158
|
+
return result;
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if (span) {
|
|
161
|
+
span.setTag("error", error);
|
|
162
|
+
}
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function traceServerAction(name, fn) {
|
|
168
|
+
const spanName = name.startsWith("server.action.") ? name : `server.action.${name}`;
|
|
169
|
+
const traced = async (...args) => {
|
|
170
|
+
return withTrace(spanName, async (span) => {
|
|
171
|
+
if (span) {
|
|
172
|
+
span.setTag("component", "server-action");
|
|
173
|
+
}
|
|
174
|
+
const result = await fn(...args);
|
|
175
|
+
return result;
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
return traced;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/utils/api-client.ts
|
|
182
|
+
async function authenticatedFetch(url, options = {}) {
|
|
183
|
+
const { token, ...fetchOptions } = options;
|
|
184
|
+
const headers = new Headers(fetchOptions.headers);
|
|
185
|
+
if (token) {
|
|
186
|
+
headers.set("authorization", `Bearer ${token}`);
|
|
187
|
+
}
|
|
188
|
+
const response = await fetch(url, {
|
|
189
|
+
...fetchOptions,
|
|
190
|
+
headers
|
|
191
|
+
});
|
|
192
|
+
if (response.status === 401) {
|
|
193
|
+
await handle401();
|
|
194
|
+
}
|
|
195
|
+
if (response.status === 502 || response.status === 503 || response.status === 504) {
|
|
196
|
+
await handleServerError(response.status);
|
|
197
|
+
}
|
|
198
|
+
return response;
|
|
199
|
+
}
|
|
200
|
+
async function handle401() {
|
|
201
|
+
const { redirect } = await import('next/navigation');
|
|
202
|
+
return redirect("/?expired=1");
|
|
203
|
+
}
|
|
204
|
+
async function handleServerError(statusCode) {
|
|
205
|
+
const { redirect } = await import('next/navigation');
|
|
206
|
+
let sourceUrl;
|
|
207
|
+
try {
|
|
208
|
+
const { headers } = await import('next/headers');
|
|
209
|
+
const headersList = await headers();
|
|
210
|
+
const referer = headersList.get("referer");
|
|
211
|
+
const host = headersList.get("host");
|
|
212
|
+
const pathname = headersList.get("x-invoke-path") || headersList.get("x-forwarded-path");
|
|
213
|
+
if (referer) {
|
|
214
|
+
sourceUrl = referer;
|
|
215
|
+
} else if (host && pathname) {
|
|
216
|
+
const protocol = headersList.get("x-forwarded-proto") || "https";
|
|
217
|
+
sourceUrl = `${protocol}://${host}${pathname}`;
|
|
218
|
+
}
|
|
219
|
+
} catch (error) {
|
|
220
|
+
console.debug("[portal-components] Could not determine source URL", error);
|
|
221
|
+
}
|
|
222
|
+
const params = new URLSearchParams({ code: String(statusCode) });
|
|
223
|
+
if (sourceUrl) {
|
|
224
|
+
params.set("source", sourceUrl);
|
|
225
|
+
}
|
|
226
|
+
return redirect(`/error?${params.toString()}`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// src/actions/index.ts
|
|
230
|
+
var getApiOrigin = () => {
|
|
231
|
+
return (process.env.REPLICATED_APP_ORIGIN || "https://replicated.app").replace(/\/+$/, "");
|
|
232
|
+
};
|
|
233
|
+
var defineServerAction = (definition) => definition;
|
|
234
|
+
var fetchCustomBrandingImpl = async () => {
|
|
235
|
+
const appSlug = process.env.PORTAL_APP_SLUG;
|
|
236
|
+
if (!appSlug) {
|
|
237
|
+
throw new Error("PORTAL_APP_SLUG is not configured");
|
|
238
|
+
}
|
|
239
|
+
const url = `${getApiOrigin()}/enterprise-portal/public/branding?app_slug=${encodeURIComponent(
|
|
240
|
+
appSlug
|
|
241
|
+
)}`;
|
|
242
|
+
if (process.env.NODE_ENV !== "production") {
|
|
243
|
+
console.debug(
|
|
244
|
+
"[portal-components] fetching custom branding via %s (Enterprise Portal API)",
|
|
245
|
+
url
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
const response = await fetch(url, {
|
|
249
|
+
headers: {
|
|
250
|
+
accept: "application/json"
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
if (!response.ok) {
|
|
254
|
+
throw new Error(
|
|
255
|
+
`Custom branding request failed (${response.status} ${response.statusText})`
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
const payload = await response.json();
|
|
259
|
+
const brandingObject = {
|
|
260
|
+
logo: payload.logoUrl,
|
|
261
|
+
title: payload.appName,
|
|
262
|
+
customColor1: payload.primaryColor,
|
|
263
|
+
customColor2: payload.secondaryColor,
|
|
264
|
+
favicon: payload.faviconUrl,
|
|
265
|
+
supportPortalLink: payload.supportPortalLink || ""
|
|
266
|
+
};
|
|
267
|
+
const brandingData = buffer.Buffer.from(JSON.stringify(brandingObject)).toString("base64");
|
|
268
|
+
return {
|
|
269
|
+
brandingData,
|
|
270
|
+
documentation: null
|
|
271
|
+
// Documentation not included in new API's public endpoint
|
|
272
|
+
};
|
|
273
|
+
};
|
|
274
|
+
react.cache(fetchCustomBrandingImpl);
|
|
275
|
+
var decodeJwtPayload = (token) => {
|
|
276
|
+
const parts = token.split(".");
|
|
277
|
+
if (parts.length !== 3) {
|
|
278
|
+
throw new Error("Invalid JWT received");
|
|
279
|
+
}
|
|
280
|
+
const payloadSegment = parts[1];
|
|
281
|
+
if (!payloadSegment) {
|
|
282
|
+
throw new Error("JWT payload segment missing");
|
|
283
|
+
}
|
|
284
|
+
const padded = payloadSegment.padEnd(
|
|
285
|
+
payloadSegment.length + (4 - payloadSegment.length % 4) % 4,
|
|
286
|
+
"="
|
|
287
|
+
);
|
|
288
|
+
const decoded = buffer.Buffer.from(padded, "base64").toString("utf-8");
|
|
289
|
+
return JSON.parse(decoded);
|
|
290
|
+
};
|
|
291
|
+
var getCustomerIdFromToken = (token) => {
|
|
292
|
+
const payload = decodeJwtPayload(token);
|
|
293
|
+
const customerId = payload?.customer_id || payload?.customerId;
|
|
294
|
+
if (typeof customerId !== "string" || !customerId.trim()) {
|
|
295
|
+
throw new Error("Unable to determine customer_id from session token");
|
|
296
|
+
}
|
|
297
|
+
return customerId.trim();
|
|
298
|
+
};
|
|
299
|
+
var listSupportBundles = defineServerAction({
|
|
300
|
+
id: "support/list-bundles",
|
|
301
|
+
description: "Fetches support bundles associated with the customer found in the portal session JWT.",
|
|
302
|
+
visibility: "customer",
|
|
303
|
+
tags: ["support", "bundles"],
|
|
304
|
+
async run({ token }, context) {
|
|
305
|
+
if (!token || typeof token !== "string") {
|
|
306
|
+
throw new Error("Support bundle listing requires a session token");
|
|
307
|
+
}
|
|
308
|
+
const url = `${getApiOrigin()}/enterprise-portal/support-bundles`;
|
|
309
|
+
if (process.env.NODE_ENV !== "production") {
|
|
310
|
+
console.debug("[portal-components] fetching support bundles via %s (Enterprise Portal API)", url);
|
|
311
|
+
}
|
|
312
|
+
const response = await authenticatedFetch(url, {
|
|
313
|
+
token,
|
|
314
|
+
headers: {
|
|
315
|
+
accept: "application/json"
|
|
316
|
+
},
|
|
317
|
+
signal: context?.signal
|
|
318
|
+
});
|
|
319
|
+
if (context?.signal?.aborted) {
|
|
320
|
+
throw new Error("Support bundles request was aborted");
|
|
321
|
+
}
|
|
322
|
+
if (!response.ok) {
|
|
323
|
+
throw new Error(
|
|
324
|
+
`Support bundles request failed (${response.status} ${response.statusText})`
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
const payload = await response.json();
|
|
328
|
+
const raw = payload.data;
|
|
329
|
+
const rawRecord = raw && typeof raw === "object" ? raw : void 0;
|
|
330
|
+
const parseInsights = (raw2) => {
|
|
331
|
+
if (!Array.isArray(raw2)) return void 0;
|
|
332
|
+
return raw2.filter((i) => i && typeof i === "object").map((i) => ({
|
|
333
|
+
level: String(i.level ?? ""),
|
|
334
|
+
primary: String(i.primary ?? ""),
|
|
335
|
+
key: typeof i.key === "string" ? i.key : void 0,
|
|
336
|
+
detail: typeof i.detail === "string" ? i.detail : void 0
|
|
337
|
+
}));
|
|
338
|
+
};
|
|
339
|
+
const bundles = Array.isArray(
|
|
340
|
+
rawRecord?.supportBundles
|
|
341
|
+
) ? (rawRecord?.supportBundles).map((item) => {
|
|
342
|
+
if (!item || typeof item !== "object") {
|
|
343
|
+
return {
|
|
344
|
+
id: "",
|
|
345
|
+
createdAt: void 0,
|
|
346
|
+
status: void 0,
|
|
347
|
+
size: void 0,
|
|
348
|
+
instanceId: void 0,
|
|
349
|
+
insights: void 0,
|
|
350
|
+
metadata: void 0
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
const record = item;
|
|
354
|
+
return {
|
|
355
|
+
id: String(record.id ?? ""),
|
|
356
|
+
createdAt: typeof record.createdAt === "string" ? record.createdAt : void 0,
|
|
357
|
+
status: typeof record.status === "string" ? record.status : void 0,
|
|
358
|
+
size: typeof record.size === "number" ? record.size : void 0,
|
|
359
|
+
instanceId: typeof record.instanceId === "string" ? record.instanceId : void 0,
|
|
360
|
+
insights: parseInsights(record.insights),
|
|
361
|
+
metadata: record
|
|
362
|
+
};
|
|
363
|
+
}) : Array.isArray(raw) ? raw.map((item) => {
|
|
364
|
+
if (!item || typeof item !== "object") {
|
|
365
|
+
return {
|
|
366
|
+
id: "",
|
|
367
|
+
createdAt: void 0,
|
|
368
|
+
status: void 0,
|
|
369
|
+
size: void 0,
|
|
370
|
+
instanceId: void 0,
|
|
371
|
+
insights: void 0,
|
|
372
|
+
metadata: void 0
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
const record = item;
|
|
376
|
+
return {
|
|
377
|
+
id: String(record.id ?? ""),
|
|
378
|
+
createdAt: typeof record.createdAt === "string" ? record.createdAt : void 0,
|
|
379
|
+
status: typeof record.status === "string" ? record.status : void 0,
|
|
380
|
+
size: typeof record.size === "number" ? record.size : void 0,
|
|
381
|
+
instanceId: typeof record.instanceId === "string" ? record.instanceId : void 0,
|
|
382
|
+
insights: parseInsights(record.insights),
|
|
383
|
+
metadata: record
|
|
384
|
+
};
|
|
385
|
+
}) : [];
|
|
386
|
+
const totalCount = (() => {
|
|
387
|
+
if (rawRecord) {
|
|
388
|
+
if (typeof rawRecord.totalCount === "number" && Number.isFinite(rawRecord.totalCount)) {
|
|
389
|
+
return rawRecord.totalCount;
|
|
390
|
+
}
|
|
391
|
+
if (Array.isArray(rawRecord.supportBundles)) {
|
|
392
|
+
return rawRecord.supportBundles.length;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (Array.isArray(raw)) {
|
|
396
|
+
return raw.length;
|
|
397
|
+
}
|
|
398
|
+
return bundles.length;
|
|
399
|
+
})();
|
|
400
|
+
return {
|
|
401
|
+
bundles,
|
|
402
|
+
totalCount,
|
|
403
|
+
raw
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
var downloadSupportBundle = defineServerAction({
|
|
408
|
+
id: "support/download-bundle",
|
|
409
|
+
description: "Gets a signed URL for downloading a support bundle.",
|
|
410
|
+
visibility: "customer",
|
|
411
|
+
tags: ["support", "bundles", "download"],
|
|
412
|
+
async run({ token, bundleId }, context) {
|
|
413
|
+
if (!token || typeof token !== "string") {
|
|
414
|
+
throw new Error("Support bundle download requires a session token");
|
|
415
|
+
}
|
|
416
|
+
if (!bundleId || typeof bundleId !== "string") {
|
|
417
|
+
throw new Error("Support bundle download requires a bundle ID");
|
|
418
|
+
}
|
|
419
|
+
const customerId = getCustomerIdFromToken(token);
|
|
420
|
+
const endpoint = `${getApiOrigin()}/enterprise-portal/support-bundles/${encodeURIComponent(bundleId)}/download?customer_id=${encodeURIComponent(customerId)}`;
|
|
421
|
+
if (process.env.NODE_ENV !== "production") {
|
|
422
|
+
console.debug("[portal-components] getting support bundle download URL via %s", endpoint);
|
|
423
|
+
}
|
|
424
|
+
const response = await authenticatedFetch(endpoint, {
|
|
425
|
+
method: "GET",
|
|
426
|
+
token,
|
|
427
|
+
headers: {
|
|
428
|
+
accept: "application/json"
|
|
429
|
+
},
|
|
430
|
+
signal: context?.signal
|
|
431
|
+
});
|
|
432
|
+
if (!response.ok) {
|
|
433
|
+
const errorText = await response.text().catch(() => "");
|
|
434
|
+
throw new Error(
|
|
435
|
+
`Support bundle download URL request failed (${response.status} ${response.statusText}): ${errorText}`
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
const data = await response.json();
|
|
439
|
+
const signedUrl = data?.signedUrl;
|
|
440
|
+
if (typeof signedUrl !== "string" || !signedUrl) {
|
|
441
|
+
throw new Error("Support bundle download response missing signedUrl");
|
|
442
|
+
}
|
|
443
|
+
return { signedUrl };
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
var deleteSupportBundle = defineServerAction({
|
|
447
|
+
id: "support/delete-bundle",
|
|
448
|
+
description: "Deletes a support bundle.",
|
|
449
|
+
visibility: "customer",
|
|
450
|
+
tags: ["support", "bundles", "delete"],
|
|
451
|
+
async run({ token, bundleId }, context) {
|
|
452
|
+
if (!token || typeof token !== "string") {
|
|
453
|
+
throw new Error("Support bundle deletion requires a session token");
|
|
454
|
+
}
|
|
455
|
+
if (!bundleId || typeof bundleId !== "string") {
|
|
456
|
+
throw new Error("Support bundle deletion requires a bundle ID");
|
|
457
|
+
}
|
|
458
|
+
const customerId = getCustomerIdFromToken(token);
|
|
459
|
+
const endpoint = `${getApiOrigin()}/enterprise-portal/support-bundles/${encodeURIComponent(bundleId)}?customer_id=${encodeURIComponent(customerId)}`;
|
|
460
|
+
if (process.env.NODE_ENV !== "production") {
|
|
461
|
+
console.debug("[portal-components] deleting support bundle via %s", endpoint);
|
|
462
|
+
}
|
|
463
|
+
const response = await authenticatedFetch(endpoint, {
|
|
464
|
+
method: "DELETE",
|
|
465
|
+
token,
|
|
466
|
+
headers: {
|
|
467
|
+
accept: "application/json"
|
|
468
|
+
},
|
|
469
|
+
signal: context?.signal
|
|
470
|
+
});
|
|
471
|
+
if (!response.ok) {
|
|
472
|
+
const errorText = await response.text().catch(() => "");
|
|
473
|
+
if (response.status === 404) {
|
|
474
|
+
throw new Error("Support bundle not found");
|
|
475
|
+
}
|
|
476
|
+
throw new Error(
|
|
477
|
+
`Support bundle deletion failed (${response.status} ${response.statusText}): ${errorText}`
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
return { success: true };
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
// src/actions/support-bundles.ts
|
|
485
|
+
async function downloadSupportBundleActionImpl(bundleId) {
|
|
486
|
+
const sessionStore = await headers.cookies();
|
|
487
|
+
const session = sessionStore.get("portal_session");
|
|
488
|
+
if (!session?.value) {
|
|
489
|
+
return { success: false, error: "Not authenticated" };
|
|
490
|
+
}
|
|
491
|
+
try {
|
|
492
|
+
const result = await downloadSupportBundle.run({
|
|
493
|
+
token: session.value,
|
|
494
|
+
bundleId
|
|
495
|
+
});
|
|
496
|
+
return { success: true, signedUrl: result.signedUrl };
|
|
497
|
+
} catch (error) {
|
|
498
|
+
console.error("[support-bundles] download failed", error);
|
|
499
|
+
return {
|
|
500
|
+
success: false,
|
|
501
|
+
error: error instanceof Error ? error.message : "Failed to download bundle"
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
var downloadSupportBundleAction = traceServerAction("downloadSupportBundleAction", downloadSupportBundleActionImpl);
|
|
506
|
+
async function deleteSupportBundleActionImpl(bundleId) {
|
|
507
|
+
const sessionStore = await headers.cookies();
|
|
508
|
+
const session = sessionStore.get("portal_session");
|
|
509
|
+
if (!session?.value) {
|
|
510
|
+
return { success: false, error: "Not authenticated" };
|
|
511
|
+
}
|
|
512
|
+
try {
|
|
513
|
+
await deleteSupportBundle.run({
|
|
514
|
+
token: session.value,
|
|
515
|
+
bundleId
|
|
516
|
+
});
|
|
517
|
+
return { success: true };
|
|
518
|
+
} catch (error) {
|
|
519
|
+
console.error("[support-bundles] delete failed", error);
|
|
520
|
+
return {
|
|
521
|
+
success: false,
|
|
522
|
+
error: error instanceof Error ? error.message : "Failed to delete bundle"
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
var deleteSupportBundleAction = traceServerAction("deleteSupportBundleAction", deleteSupportBundleActionImpl);
|
|
527
|
+
async function uploadSupportBundleActionImpl(formData) {
|
|
528
|
+
const sessionStore = await headers.cookies();
|
|
529
|
+
const session = sessionStore.get("portal_session");
|
|
530
|
+
if (!session?.value) {
|
|
531
|
+
return { success: false, error: "Not authenticated" };
|
|
532
|
+
}
|
|
533
|
+
const file = formData.get("file");
|
|
534
|
+
const appId = formData.get("appId");
|
|
535
|
+
if (!file) {
|
|
536
|
+
return { success: false, error: "No file provided" };
|
|
537
|
+
}
|
|
538
|
+
if (!appId) {
|
|
539
|
+
return { success: false, error: "No app ID provided" };
|
|
540
|
+
}
|
|
541
|
+
const MAX_FILE_SIZE = 500 * 1024 * 1024;
|
|
542
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
543
|
+
return { success: false, error: "File size exceeds 500MB limit" };
|
|
544
|
+
}
|
|
545
|
+
try {
|
|
546
|
+
const endpoint = `${getApiOrigin()}/enterprise-portal/support-bundles/upload/${encodeURIComponent(appId)}`;
|
|
547
|
+
const response = await authenticatedFetch(endpoint, {
|
|
548
|
+
method: "POST",
|
|
549
|
+
token: session.value,
|
|
550
|
+
headers: {
|
|
551
|
+
"Content-Type": "application/gzip"
|
|
552
|
+
},
|
|
553
|
+
body: file,
|
|
554
|
+
// @ts-ignore - duplex is needed for streaming but not in TypeScript types yet
|
|
555
|
+
duplex: "half"
|
|
556
|
+
});
|
|
557
|
+
if (!response.ok) {
|
|
558
|
+
const errorText = await response.text().catch(() => "");
|
|
559
|
+
throw new Error(`Upload failed: ${response.status} ${response.statusText}${errorText ? `: ${errorText}` : ""}`);
|
|
560
|
+
}
|
|
561
|
+
const data = await response.json();
|
|
562
|
+
return {
|
|
563
|
+
success: true,
|
|
564
|
+
bundleId: data.bundleId,
|
|
565
|
+
bundleSlug: data.slug
|
|
566
|
+
};
|
|
567
|
+
} catch (error) {
|
|
568
|
+
console.error("[support-bundles] upload failed", error);
|
|
569
|
+
return {
|
|
570
|
+
success: false,
|
|
571
|
+
error: error instanceof Error ? error.message : "Failed to upload support bundle"
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
var uploadSupportBundleAction = traceServerAction("uploadSupportBundleAction", uploadSupportBundleActionImpl);
|
|
576
|
+
async function listSupportBundlesActionImpl() {
|
|
577
|
+
const sessionStore = await headers.cookies();
|
|
578
|
+
const session = sessionStore.get("portal_session");
|
|
579
|
+
if (!session?.value) {
|
|
580
|
+
return { success: false, error: "Not authenticated" };
|
|
581
|
+
}
|
|
582
|
+
try {
|
|
583
|
+
const result = await listSupportBundles.run({
|
|
584
|
+
token: session.value
|
|
585
|
+
});
|
|
586
|
+
return {
|
|
587
|
+
success: true,
|
|
588
|
+
bundles: result.bundles,
|
|
589
|
+
totalCount: result.totalCount
|
|
590
|
+
};
|
|
591
|
+
} catch (error) {
|
|
592
|
+
console.error("[support-bundles] list failed", error);
|
|
593
|
+
return {
|
|
594
|
+
success: false,
|
|
595
|
+
error: error instanceof Error ? error.message : "Failed to list bundles"
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
var listSupportBundlesAction = traceServerAction("listSupportBundlesAction", listSupportBundlesActionImpl);
|
|
600
|
+
|
|
601
|
+
exports.deleteSupportBundleAction = deleteSupportBundleAction;
|
|
602
|
+
exports.downloadSupportBundleAction = downloadSupportBundleAction;
|
|
603
|
+
exports.listSupportBundlesAction = listSupportBundlesAction;
|
|
604
|
+
exports.uploadSupportBundleAction = uploadSupportBundleAction;
|
|
605
|
+
//# sourceMappingURL=support-bundles.js.map
|
|
606
|
+
//# sourceMappingURL=support-bundles.js.map
|