@streamoid/settings 0.7.5 → 0.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.d.mts +9 -5
- package/dist/index.d.ts +9 -5
- package/dist/index.js +239 -159
- package/dist/index.mjs +247 -167
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -67,6 +67,161 @@ __export(index_exports, {
|
|
|
67
67
|
});
|
|
68
68
|
module.exports = __toCommonJS(index_exports);
|
|
69
69
|
|
|
70
|
+
// src/settings-errors.ts
|
|
71
|
+
function quietErrorToast(toast) {
|
|
72
|
+
return { ...toast, error(message) {
|
|
73
|
+
if (message.trim()) toast.error(message);
|
|
74
|
+
} };
|
|
75
|
+
}
|
|
76
|
+
function isOnlyWorkspaceAdmin(failure) {
|
|
77
|
+
const seen = /* @__PURE__ */ new Set();
|
|
78
|
+
const visit = (value, depth) => {
|
|
79
|
+
if (depth > 4 || value == null || seen.has(value)) return false;
|
|
80
|
+
if (typeof value === "string") return /single admin|only admin/i.test(value);
|
|
81
|
+
if (typeof value !== "object") return false;
|
|
82
|
+
seen.add(value);
|
|
83
|
+
const error = value;
|
|
84
|
+
return [error.body, error.data, error.status, error.message, error.error, error.cause].some((child) => visit(child, depth + 1));
|
|
85
|
+
};
|
|
86
|
+
return visit(failure, 0);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ../errors/index.js
|
|
90
|
+
var actions = /* @__PURE__ */ new Set(["edit_input", "sign_in", "ask_admin", "wait", "view_status", "retry", "contact_support"]);
|
|
91
|
+
var states = /* @__PURE__ */ new Set(["not_started", "failed", "partial", "in_progress", "unknown"]);
|
|
92
|
+
var isObject = (value) => value !== null && typeof value === "object";
|
|
93
|
+
var object = (value) => isObject(value) ? value : {};
|
|
94
|
+
var text = (value) => typeof value === "string" ? value : "";
|
|
95
|
+
var reference = (value) => /^[a-zA-Z0-9][a-zA-Z0-9_-]{5,127}$/.test(text(value)) ? value : void 0;
|
|
96
|
+
var technical = /https?:\/\/|<[^>]+>|\b(?:TypeError|SyntaxError|ReferenceError|ENOTFOUND|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN|Traceback|SQLSTATE|MongoServerError|localhost|undefined|null|NaN|CORS|stack trace|Xvfb|node:sqlite)\b|(?:\/[^\s/]+){3,}|\bat\s+\w+\s*\(/i;
|
|
97
|
+
var publicText = (value) => {
|
|
98
|
+
const s = text(value).trim();
|
|
99
|
+
return s && s.length <= 500 && !technical.test(s) && !/[\r\n{}]/.test(s) ? s : void 0;
|
|
100
|
+
};
|
|
101
|
+
var isCancellation = (error) => object(error).name === "AbortError";
|
|
102
|
+
function parseRetryAfter(value, now = Date.now()) {
|
|
103
|
+
if (!text(value).trim()) return void 0;
|
|
104
|
+
const seconds = /^\d+$/.test(value.trim()) ? Number(value) : Math.ceil((Date.parse(value) - now) / 1e3);
|
|
105
|
+
return Number.isFinite(seconds) && seconds >= 0 && seconds <= 86400 ? seconds : void 0;
|
|
106
|
+
}
|
|
107
|
+
function validationFields(body) {
|
|
108
|
+
if (!Array.isArray(body.detail)) return [];
|
|
109
|
+
return body.detail.slice(0, 20).flatMap((issue) => {
|
|
110
|
+
if (!isObject(issue) || !Array.isArray(issue.loc)) return [];
|
|
111
|
+
const path = issue.loc.filter((part) => part !== "body" && part !== "query").filter((part) => typeof part === "string" || typeof part === "number").join(".");
|
|
112
|
+
if (!/^[a-zA-Z0-9_.-]{1,150}$/.test(path)) return [];
|
|
113
|
+
return [{ path, message: issue.type === "missing" || issue.type === "value_error.missing" ? "This field is required." : "Check this value and try again." }];
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
var known = {
|
|
117
|
+
"platform.session_expired": ["Your session has expired. Sign in to continue.", "sign_in"],
|
|
118
|
+
"platform.permission_denied": ["You don't have permission to do this. Ask a workspace admin for access.", "ask_admin"],
|
|
119
|
+
"platform.insufficient_credits": ["There aren't enough credits for this action. Ask your billing admin to add credits.", "ask_admin"],
|
|
120
|
+
"platform.invalid_input": ["Check the information you entered and correct any highlighted fields.", "edit_input"],
|
|
121
|
+
"platform.not_found": ["This item is no longer available or you don't have access to it. Check that you've opened the correct workspace.", "view_status"],
|
|
122
|
+
"platform.conflict": ["This item has changed or already exists. Check its current state before continuing.", "view_status"],
|
|
123
|
+
"platform.file_too_large": ["This file is too large. Choose a smaller file and try again.", "edit_input"],
|
|
124
|
+
"platform.unsupported_file": ["This file type isn't supported. Choose one of the accepted file types.", "edit_input"],
|
|
125
|
+
"platform.content_rejected": ["This request couldn't be completed with the current input. Review the image or description and try again.", "edit_input"],
|
|
126
|
+
"platform.rate_limited": ["This service is busy. Wait a moment before trying again.", "wait"],
|
|
127
|
+
"platform.service_unavailable": ["A service is temporarily unavailable. Try again shortly; contact support if it keeps happening.", "wait"],
|
|
128
|
+
"platform.setup_required": ["There's a setup problem on our side. Contact support so we can help.", "contact_support"],
|
|
129
|
+
"platform.network_error": ["We couldn't reach the service. Check your connection and try again shortly.", "retry"],
|
|
130
|
+
"platform.unexpected": ["We couldn't complete this action. Contact support if it keeps happening.", "contact_support"]
|
|
131
|
+
};
|
|
132
|
+
function inferCode(status, rawCode, diagnostic) {
|
|
133
|
+
if (Object.hasOwn(known, rawCode)) return rawCode;
|
|
134
|
+
const signal = `${rawCode} ${diagnostic}`;
|
|
135
|
+
if (/insufficient.?credits|credits.?unavailable|insufficient.?balance/i.test(signal)) return "platform.insufficient_credits";
|
|
136
|
+
if (/content.?policy|safety.?block|content.?reject/i.test(signal)) return "platform.content_rejected";
|
|
137
|
+
if (/rate.?limit|capacity.?limit/i.test(signal)) return "platform.rate_limited";
|
|
138
|
+
if (status === 401) return "platform.session_expired";
|
|
139
|
+
if (status === 402) return "platform.insufficient_credits";
|
|
140
|
+
if (status === 403) return "platform.permission_denied";
|
|
141
|
+
if (status === 404 || status === 410) return "platform.not_found";
|
|
142
|
+
if (status === 409 || status === 412) return "platform.conflict";
|
|
143
|
+
if (status === 413) return "platform.file_too_large";
|
|
144
|
+
if (status === 415) return "platform.unsupported_file";
|
|
145
|
+
if (status === 429) return "platform.rate_limited";
|
|
146
|
+
if (status === 400 || status === 422) return "platform.invalid_input";
|
|
147
|
+
if ([408, 502, 503, 504].includes(status)) return "platform.service_unavailable";
|
|
148
|
+
if (/ENOTFOUND|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN|server misbehaving|upstream unavailable/i.test(signal)) return "platform.service_unavailable";
|
|
149
|
+
if (/failed to fetch|networkerror|network request failed|load failed/i.test(signal)) return "platform.network_error";
|
|
150
|
+
return "platform.unexpected";
|
|
151
|
+
}
|
|
152
|
+
function normalizeError(failure, options = {}) {
|
|
153
|
+
if (failure instanceof UserFacingError && Object.keys(options).length === 0) return failure.publicError;
|
|
154
|
+
const error = object(failure);
|
|
155
|
+
const body = object(options.body ?? error.body ?? error.data ?? failure);
|
|
156
|
+
const envelope = object(body.publicError ?? error.publicError);
|
|
157
|
+
const declared = envelope.version === 1 ? envelope : {};
|
|
158
|
+
const status = Number(options.status ?? error.statusCode ?? (typeof error.status === "number" ? error.status : void 0)) || 0;
|
|
159
|
+
const diagnostic = [text(error.message), text(failure), text(body.detail), text(body.error)].filter(Boolean).join(" ");
|
|
160
|
+
const rawCode = text(declared.code) || text(object(body.error).code) || text(body.code) || text(error.code);
|
|
161
|
+
const category = inferCode(status, rawCode, diagnostic);
|
|
162
|
+
const code = /^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+$/.test(text(declared.code)) ? declared.code : category;
|
|
163
|
+
const method = (options.method || text(error.method) || "UNKNOWN").toUpperCase();
|
|
164
|
+
const read = ["GET", "HEAD", "OPTIONS"].includes(method);
|
|
165
|
+
const suppliedState = object(declared.operation).state;
|
|
166
|
+
const state = states.has(suppliedState) ? suppliedState : read ? "failed" : "unknown";
|
|
167
|
+
const retryAfterSeconds = parseRetryAfter(options.retryAfter) ?? (Number.isFinite(declared.recovery?.retryAfterSeconds) && declared.recovery.retryAfterSeconds >= 0 && declared.recovery.retryAfterSeconds <= 86400 ? declared.recovery.retryAfterSeconds : void 0);
|
|
168
|
+
let [message, action] = known[category];
|
|
169
|
+
message = publicText(declared.message) || message;
|
|
170
|
+
if (actions.has(declared.recovery?.action)) action = declared.recovery.action;
|
|
171
|
+
const fieldErrors = Array.isArray(declared.fieldErrors) && declared.fieldErrors.length ? declared.fieldErrors.slice(0, 20).filter((item) => /^[a-zA-Z0-9_.-]{1,150}$/.test(text(item?.path)) && publicText(item?.message)).map((item) => ({ path: item.path, message: item.message })) : validationFields(body);
|
|
172
|
+
if (fieldErrors.length) {
|
|
173
|
+
const fields = fieldErrors.slice(0, 3).map((field) => `${field.path.replace(/_/g, " ")}: ${field.message}`).join(" ");
|
|
174
|
+
message = `${fields}${fieldErrors.length > 3 ? " Check the remaining fields too." : ""}`;
|
|
175
|
+
action = "edit_input";
|
|
176
|
+
}
|
|
177
|
+
if (category === "platform.rate_limited" && retryAfterSeconds !== void 0 && !publicText(declared.message)) {
|
|
178
|
+
const unit = retryAfterSeconds >= 3600 ? "hour" : retryAfterSeconds >= 60 ? "minute" : "second";
|
|
179
|
+
const amount = Math.ceil(retryAfterSeconds / (unit === "hour" ? 3600 : unit === "minute" ? 60 : 1));
|
|
180
|
+
message = `This service is busy. Try again in ${amount} ${unit}${amount === 1 ? "" : "s"}.`;
|
|
181
|
+
}
|
|
182
|
+
const uncertain = !read && state === "unknown" && ["platform.network_error", "platform.service_unavailable", "platform.unexpected"].includes(category);
|
|
183
|
+
if (uncertain) {
|
|
184
|
+
const uncertainty = "We couldn't confirm whether your request completed. Check its status before trying again; contact support if you're unsure.";
|
|
185
|
+
const authored = publicText(declared.message);
|
|
186
|
+
message = authored ? authored.endsWith(uncertainty) ? authored : `${authored} ${uncertainty}` : uncertainty;
|
|
187
|
+
action = "view_status";
|
|
188
|
+
}
|
|
189
|
+
const operationLabel = publicText(options.operation);
|
|
190
|
+
if (operationLabel && !message.startsWith(`We couldn't ${operationLabel}.`)) message = `We couldn't ${operationLabel}. ${message}`;
|
|
191
|
+
const errorRef = reference(options.reference) || reference(declared.reference) || reference(error.errorRef) || reference(object(body.error).ref);
|
|
192
|
+
const safeToRetry = (read || declared.safeToRetry === true && ["not_started", "failed"].includes(state)) && ["wait", "retry"].includes(action);
|
|
193
|
+
return {
|
|
194
|
+
version: 1,
|
|
195
|
+
code,
|
|
196
|
+
message,
|
|
197
|
+
recovery: { action, ...retryAfterSeconds !== void 0 ? { retryAfterSeconds } : {} },
|
|
198
|
+
operation: { state, ...reference(object(declared.operation).id) ? { id: declared.operation.id } : {} },
|
|
199
|
+
safeToRetry,
|
|
200
|
+
fieldErrors,
|
|
201
|
+
...errorRef ? { reference: errorRef } : {}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
var UserFacingError = class extends Error {
|
|
205
|
+
constructor(failure, options = {}) {
|
|
206
|
+
const normalized = normalizeError(failure, options);
|
|
207
|
+
super(normalized.message, { cause: failure });
|
|
208
|
+
this.name = "UserFacingError";
|
|
209
|
+
this.publicError = normalized;
|
|
210
|
+
this.status = Number(options.status ?? object(failure).status) || 0;
|
|
211
|
+
this.statusCode = this.status;
|
|
212
|
+
this.method = (options.method || text(object(failure).method) || "UNKNOWN").toUpperCase();
|
|
213
|
+
this.code = normalized.code;
|
|
214
|
+
this.body = options.body ?? object(failure).body;
|
|
215
|
+
this.data = this.body;
|
|
216
|
+
this.errorRef = normalized.reference ?? null;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
function errorMessage(failure, options = {}) {
|
|
220
|
+
if (isCancellation(failure)) return "";
|
|
221
|
+
const normalized = normalizeError(failure, options);
|
|
222
|
+
return normalized.reference ? `${normalized.message} Reference: ${normalized.reference}` : normalized.message;
|
|
223
|
+
}
|
|
224
|
+
|
|
70
225
|
// src/managed-organization-summary.tsx
|
|
71
226
|
var import_icons = require("@streamoid/icons");
|
|
72
227
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -293,7 +448,13 @@ function SettingsAdaptersProvider({
|
|
|
293
448
|
adapters,
|
|
294
449
|
children
|
|
295
450
|
}) {
|
|
296
|
-
|
|
451
|
+
const value = (0, import_react2.useMemo)(() => {
|
|
452
|
+
const toast = quietErrorToast(adapters.toast);
|
|
453
|
+
return new Proxy(adapters, { get(target, key) {
|
|
454
|
+
return key === "toast" ? toast : Reflect.get(target, key);
|
|
455
|
+
} });
|
|
456
|
+
}, [adapters]);
|
|
457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SettingsAdaptersContext.Provider, { value, children });
|
|
297
458
|
}
|
|
298
459
|
function useSettingsAdapters() {
|
|
299
460
|
const ctx = (0, import_react2.useContext)(SettingsAdaptersContext);
|
|
@@ -2736,7 +2897,7 @@ function ToggleSwitch({
|
|
|
2736
2897
|
}
|
|
2737
2898
|
);
|
|
2738
2899
|
}
|
|
2739
|
-
function FieldLabel2({ text }) {
|
|
2900
|
+
function FieldLabel2({ text: text2 }) {
|
|
2740
2901
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex items-center shrink-0 w-full", style: { height: 24 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2741
2902
|
"div",
|
|
2742
2903
|
{
|
|
@@ -2748,7 +2909,7 @@ function FieldLabel2({ text }) {
|
|
|
2748
2909
|
lineHeight: T6.lhSm,
|
|
2749
2910
|
color: T6.tertiary
|
|
2750
2911
|
},
|
|
2751
|
-
children:
|
|
2912
|
+
children: text2
|
|
2752
2913
|
}
|
|
2753
2914
|
) });
|
|
2754
2915
|
}
|
|
@@ -4789,7 +4950,7 @@ function TeamsContent({
|
|
|
4789
4950
|
toast.success("Invitation resent");
|
|
4790
4951
|
await fetchData();
|
|
4791
4952
|
} catch (err) {
|
|
4792
|
-
const msg = err
|
|
4953
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
4793
4954
|
toast.error(msg);
|
|
4794
4955
|
}
|
|
4795
4956
|
closeModal();
|
|
@@ -4824,17 +4985,13 @@ function TeamsContent({
|
|
|
4824
4985
|
storeIds: permissions.catalogixStores || []
|
|
4825
4986
|
});
|
|
4826
4987
|
toast.success("User permissions updated");
|
|
4827
|
-
await fetchData();
|
|
4828
4988
|
} catch (err) {
|
|
4829
|
-
const msg = err
|
|
4989
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
4830
4990
|
toast.error(msg);
|
|
4831
|
-
|
|
4832
|
-
(m) => m.id === modal.target?.id ? { ...m, permissions } : m
|
|
4833
|
-
);
|
|
4834
|
-
setActiveMembers(updateList);
|
|
4835
|
-
setPendingMembers(updateList);
|
|
4991
|
+
return;
|
|
4836
4992
|
}
|
|
4837
4993
|
closeModal();
|
|
4994
|
+
await fetchData();
|
|
4838
4995
|
};
|
|
4839
4996
|
const handleRemove = async () => {
|
|
4840
4997
|
if (!modal.target) {
|
|
@@ -4869,16 +5026,13 @@ function TeamsContent({
|
|
|
4869
5026
|
} else {
|
|
4870
5027
|
throw new Error("Unable to identify target to remove");
|
|
4871
5028
|
}
|
|
4872
|
-
await fetchData();
|
|
4873
5029
|
} catch (err) {
|
|
4874
|
-
const msg = err
|
|
5030
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
4875
5031
|
toast.error(msg);
|
|
4876
|
-
|
|
4877
|
-
setPendingMembers(
|
|
4878
|
-
(prev) => prev.filter((m) => m.id !== modal.target?.id)
|
|
4879
|
-
);
|
|
5032
|
+
return;
|
|
4880
5033
|
}
|
|
4881
5034
|
closeModal();
|
|
5035
|
+
await fetchData();
|
|
4882
5036
|
};
|
|
4883
5037
|
const handleCancelPendingInvite = async (member) => {
|
|
4884
5038
|
if (member.kind !== "invite" || !member.invitationId) {
|
|
@@ -4904,7 +5058,7 @@ function TeamsContent({
|
|
|
4904
5058
|
toast.success("Invitation removed");
|
|
4905
5059
|
await fetchData();
|
|
4906
5060
|
} catch (err) {
|
|
4907
|
-
const msg = err
|
|
5061
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
4908
5062
|
toast.error(msg);
|
|
4909
5063
|
}
|
|
4910
5064
|
};
|
|
@@ -4921,7 +5075,7 @@ function TeamsContent({
|
|
|
4921
5075
|
toast.success("Invitation resent");
|
|
4922
5076
|
await fetchData();
|
|
4923
5077
|
} catch (err) {
|
|
4924
|
-
const msg = err
|
|
5078
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
4925
5079
|
toast.error(msg);
|
|
4926
5080
|
}
|
|
4927
5081
|
};
|
|
@@ -4950,7 +5104,7 @@ function TeamsContent({
|
|
|
4950
5104
|
await fetchData();
|
|
4951
5105
|
closeModal();
|
|
4952
5106
|
} catch (err) {
|
|
4953
|
-
const msg = err
|
|
5107
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
4954
5108
|
toast.error(msg);
|
|
4955
5109
|
}
|
|
4956
5110
|
};
|
|
@@ -5166,7 +5320,7 @@ var T9 = {
|
|
|
5166
5320
|
r4xl: "var(--radius-4xl)",
|
|
5167
5321
|
neutral300: "var(--primitives-neutral-300)"
|
|
5168
5322
|
};
|
|
5169
|
-
function FieldLabel3({ text }) {
|
|
5323
|
+
function FieldLabel3({ text: text2 }) {
|
|
5170
5324
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex items-center shrink-0 w-full", style: { height: 24 }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
5171
5325
|
"div",
|
|
5172
5326
|
{
|
|
@@ -5178,7 +5332,7 @@ function FieldLabel3({ text }) {
|
|
|
5178
5332
|
lineHeight: T9.lhSm,
|
|
5179
5333
|
color: T9.tertiary
|
|
5180
5334
|
},
|
|
5181
|
-
children:
|
|
5335
|
+
children: text2
|
|
5182
5336
|
}
|
|
5183
5337
|
) });
|
|
5184
5338
|
}
|
|
@@ -6133,7 +6287,11 @@ function MemberRow({
|
|
|
6133
6287
|
}
|
|
6134
6288
|
);
|
|
6135
6289
|
}
|
|
6136
|
-
function WorkspaceRow({
|
|
6290
|
+
function WorkspaceRow({
|
|
6291
|
+
workspace,
|
|
6292
|
+
joining = false,
|
|
6293
|
+
onJoin
|
|
6294
|
+
}) {
|
|
6137
6295
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
6138
6296
|
"div",
|
|
6139
6297
|
{
|
|
@@ -6169,80 +6327,19 @@ function WorkspaceRow({ workspace }) {
|
|
|
6169
6327
|
}
|
|
6170
6328
|
)
|
|
6171
6329
|
] }),
|
|
6172
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
}
|
|
6177
|
-
function JoinableWorkspaceRow({
|
|
6178
|
-
workspace,
|
|
6179
|
-
joining,
|
|
6180
|
-
onJoin
|
|
6181
|
-
}) {
|
|
6182
|
-
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
6183
|
-
"div",
|
|
6184
|
-
{
|
|
6185
|
-
className: "flex items-center self-stretch shrink-0",
|
|
6186
|
-
style: {
|
|
6187
|
-
borderBottom: `1px solid ${T11.borderSubtle}`,
|
|
6188
|
-
padding: `${T11.spXl} ${T11.sp3xl}`,
|
|
6189
|
-
gap: T11.sp6xl
|
|
6190
|
-
},
|
|
6191
|
-
children: [
|
|
6192
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center min-w-0", style: { flex: 1, gap: T11.spMd }, children: [
|
|
6193
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
6194
|
-
ProfileAvatar,
|
|
6330
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center shrink-0", style: { gap: T11.spMd }, children: [
|
|
6331
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(VisibilityBadge, { visibility: workspace.orgVisibility }),
|
|
6332
|
+
onJoin && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
6333
|
+
import_ui8.ScButton,
|
|
6195
6334
|
{
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
size:
|
|
6199
|
-
|
|
6335
|
+
text: joining ? "Joining\u2026" : "Join",
|
|
6336
|
+
variant: "secondary",
|
|
6337
|
+
size: "sm",
|
|
6338
|
+
state: joining ? "disabled" : "default",
|
|
6339
|
+
onClick: joining ? void 0 : onJoin
|
|
6200
6340
|
}
|
|
6201
|
-
)
|
|
6202
|
-
|
|
6203
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
6204
|
-
"span",
|
|
6205
|
-
{
|
|
6206
|
-
className: "truncate",
|
|
6207
|
-
style: {
|
|
6208
|
-
fontFamily: T11.font,
|
|
6209
|
-
fontSize: T11.fsSm,
|
|
6210
|
-
fontWeight: 500,
|
|
6211
|
-
lineHeight: T11.lhSm,
|
|
6212
|
-
color: T11.primary
|
|
6213
|
-
},
|
|
6214
|
-
children: workspace.name
|
|
6215
|
-
}
|
|
6216
|
-
),
|
|
6217
|
-
workspace.ownerName && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
6218
|
-
"span",
|
|
6219
|
-
{
|
|
6220
|
-
className: "truncate",
|
|
6221
|
-
style: {
|
|
6222
|
-
fontFamily: T11.font,
|
|
6223
|
-
fontSize: T11.fsXs,
|
|
6224
|
-
fontWeight: 400,
|
|
6225
|
-
lineHeight: T11.lhXs,
|
|
6226
|
-
color: T11.muted
|
|
6227
|
-
},
|
|
6228
|
-
children: [
|
|
6229
|
-
"Created by ",
|
|
6230
|
-
workspace.ownerName
|
|
6231
|
-
]
|
|
6232
|
-
}
|
|
6233
|
-
)
|
|
6234
|
-
] })
|
|
6235
|
-
] }),
|
|
6236
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
6237
|
-
import_ui8.ScButton,
|
|
6238
|
-
{
|
|
6239
|
-
text: joining ? "Joining\u2026" : "Join",
|
|
6240
|
-
variant: "secondary",
|
|
6241
|
-
size: "sm",
|
|
6242
|
-
state: joining ? "disabled" : "default",
|
|
6243
|
-
onClick: joining ? void 0 : onJoin
|
|
6244
|
-
}
|
|
6245
|
-
)
|
|
6341
|
+
)
|
|
6342
|
+
] })
|
|
6246
6343
|
]
|
|
6247
6344
|
}
|
|
6248
6345
|
);
|
|
@@ -6370,8 +6467,7 @@ function OrganizationContent({
|
|
|
6370
6467
|
const current = organization.current;
|
|
6371
6468
|
const [members, setMembers] = (0, import_react12.useState)([]);
|
|
6372
6469
|
const [workspaces, setWorkspaces] = (0, import_react12.useState)([]);
|
|
6373
|
-
const canJoinShared = current?.role === "member" && !!organization.
|
|
6374
|
-
const [joinable, setJoinable] = (0, import_react12.useState)([]);
|
|
6470
|
+
const canJoinShared = current?.role === "member" && !!organization.joinWorkspaces;
|
|
6375
6471
|
const [joiningId, setJoiningId] = (0, import_react12.useState)(null);
|
|
6376
6472
|
const [joinRequests, setJoinRequests] = (0, import_react12.useState)([]);
|
|
6377
6473
|
const [highestRole, setHighestRole] = (0, import_react12.useState)("guest");
|
|
@@ -6382,20 +6478,12 @@ function OrganizationContent({
|
|
|
6382
6478
|
if (!organization.current) return;
|
|
6383
6479
|
setLoadingData(true);
|
|
6384
6480
|
try {
|
|
6385
|
-
const [
|
|
6386
|
-
membersRes,
|
|
6387
|
-
workspacesRes,
|
|
6388
|
-
joinRequestsRes,
|
|
6389
|
-
highestRoleRes,
|
|
6390
|
-
joinableRes
|
|
6391
|
-
] = await Promise.all([
|
|
6481
|
+
const [membersRes, workspacesRes, joinRequestsRes, highestRoleRes] = await Promise.all([
|
|
6392
6482
|
organization.fetchMembers().catch(() => null),
|
|
6393
6483
|
organization.fetchWorkspaces().catch(() => null),
|
|
6394
6484
|
organization.fetchJoinRequests().catch(() => null),
|
|
6395
|
-
organization.getHighestRole?.().catch(() => null) ?? Promise.resolve(null)
|
|
6396
|
-
canJoinShared ? organization.fetchJoinableWorkspaces().catch(() => null) : Promise.resolve(null)
|
|
6485
|
+
organization.getHighestRole?.().catch(() => null) ?? Promise.resolve(null)
|
|
6397
6486
|
]);
|
|
6398
|
-
if (joinableRes) setJoinable(joinableRes);
|
|
6399
6487
|
if (highestRoleRes?.role) setHighestRole(highestRoleRes.role);
|
|
6400
6488
|
if (membersRes) setMembers(membersRes.filter((m) => m?.user));
|
|
6401
6489
|
if (workspacesRes) setWorkspaces(workspacesRes);
|
|
@@ -6404,7 +6492,7 @@ function OrganizationContent({
|
|
|
6404
6492
|
} finally {
|
|
6405
6493
|
setLoadingData(false);
|
|
6406
6494
|
}
|
|
6407
|
-
}, [organization
|
|
6495
|
+
}, [organization]);
|
|
6408
6496
|
(0, import_react12.useEffect)(() => {
|
|
6409
6497
|
fetchData();
|
|
6410
6498
|
}, [fetchData]);
|
|
@@ -6421,9 +6509,7 @@ function OrganizationContent({
|
|
|
6421
6509
|
await workspaceAdapter.refresh?.().catch(() => void 0);
|
|
6422
6510
|
await fetchData();
|
|
6423
6511
|
} catch (err) {
|
|
6424
|
-
toast.error(
|
|
6425
|
-
err instanceof Error ? err.message : `Couldn't join ${target.name}`
|
|
6426
|
-
);
|
|
6512
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
6427
6513
|
} finally {
|
|
6428
6514
|
setJoiningId(null);
|
|
6429
6515
|
}
|
|
@@ -6436,7 +6522,7 @@ function OrganizationContent({
|
|
|
6436
6522
|
toast.success("Organization updated");
|
|
6437
6523
|
return true;
|
|
6438
6524
|
} catch (err) {
|
|
6439
|
-
toast.error(err
|
|
6525
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
6440
6526
|
return false;
|
|
6441
6527
|
}
|
|
6442
6528
|
};
|
|
@@ -6447,7 +6533,7 @@ function OrganizationContent({
|
|
|
6447
6533
|
toast.success("Organization deleted");
|
|
6448
6534
|
return true;
|
|
6449
6535
|
} catch (err) {
|
|
6450
|
-
toast.error(err
|
|
6536
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
6451
6537
|
return false;
|
|
6452
6538
|
}
|
|
6453
6539
|
};
|
|
@@ -6479,7 +6565,7 @@ function OrganizationContent({
|
|
|
6479
6565
|
toast.success("Member updated");
|
|
6480
6566
|
await fetchData();
|
|
6481
6567
|
} catch (err) {
|
|
6482
|
-
toast.error(err
|
|
6568
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
6483
6569
|
}
|
|
6484
6570
|
closeModal();
|
|
6485
6571
|
};
|
|
@@ -6509,7 +6595,7 @@ function OrganizationContent({
|
|
|
6509
6595
|
toast.success("Member removed");
|
|
6510
6596
|
await fetchData();
|
|
6511
6597
|
} catch (err) {
|
|
6512
|
-
toast.error(err
|
|
6598
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
6513
6599
|
}
|
|
6514
6600
|
closeModal();
|
|
6515
6601
|
};
|
|
@@ -6521,7 +6607,7 @@ function OrganizationContent({
|
|
|
6521
6607
|
);
|
|
6522
6608
|
await fetchData();
|
|
6523
6609
|
} catch (err) {
|
|
6524
|
-
toast.error(err
|
|
6610
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
6525
6611
|
}
|
|
6526
6612
|
};
|
|
6527
6613
|
const handleRejectJoinRequest = async (request) => {
|
|
@@ -6530,7 +6616,7 @@ function OrganizationContent({
|
|
|
6530
6616
|
toast.success("Request rejected");
|
|
6531
6617
|
await fetchData();
|
|
6532
6618
|
} catch (err) {
|
|
6533
|
-
toast.error(err
|
|
6619
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
6534
6620
|
}
|
|
6535
6621
|
};
|
|
6536
6622
|
if (!current) {
|
|
@@ -6653,21 +6739,12 @@ function OrganizationContent({
|
|
|
6653
6739
|
{
|
|
6654
6740
|
title: "Workspaces in this organization",
|
|
6655
6741
|
empty: workspaces.length === 0,
|
|
6656
|
-
children: workspaces.map((ws) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
6657
|
-
|
|
6658
|
-
),
|
|
6659
|
-
canJoinShared && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
6660
|
-
Section,
|
|
6661
|
-
{
|
|
6662
|
-
title: "Shared workspaces you can join",
|
|
6663
|
-
empty: joinable.length === 0,
|
|
6664
|
-
emptyText: "You're in every shared workspace in this organization",
|
|
6665
|
-
children: joinable.map((ws) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
6666
|
-
JoinableWorkspaceRow,
|
|
6742
|
+
children: workspaces.map((ws) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
6743
|
+
WorkspaceRow,
|
|
6667
6744
|
{
|
|
6668
6745
|
workspace: ws,
|
|
6669
6746
|
joining: joiningId === ws._id,
|
|
6670
|
-
onJoin: () => void handleJoinWorkspace(ws)
|
|
6747
|
+
onJoin: canJoinShared && ws.joined === false && ws.orgVisibility === "shared" ? () => void handleJoinWorkspace(ws) : void 0
|
|
6671
6748
|
},
|
|
6672
6749
|
ws._id
|
|
6673
6750
|
))
|
|
@@ -6769,6 +6846,21 @@ function OrganizationContent({
|
|
|
6769
6846
|
) });
|
|
6770
6847
|
}
|
|
6771
6848
|
|
|
6849
|
+
// src/billing-errors.ts
|
|
6850
|
+
function isBillingWorkspaceMissing(failure) {
|
|
6851
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6852
|
+
const visit = (value, depth) => {
|
|
6853
|
+
if (depth > 4 || value == null || seen.has(value)) return false;
|
|
6854
|
+
if (typeof value === "string") return /workspace.*not found/i.test(value);
|
|
6855
|
+
if (typeof value !== "object") return false;
|
|
6856
|
+
seen.add(value);
|
|
6857
|
+
const error = value;
|
|
6858
|
+
if (error.code === "billing.workspace_not_found") return true;
|
|
6859
|
+
return [error.message, error.error, error.data, error.body, error.cause, error.publicError].some((child) => visit(child, depth + 1));
|
|
6860
|
+
};
|
|
6861
|
+
return visit(failure, 0);
|
|
6862
|
+
}
|
|
6863
|
+
|
|
6772
6864
|
// src/billing-content.tsx
|
|
6773
6865
|
var import_react15 = require("react");
|
|
6774
6866
|
var import_ui9 = require("@streamoid/ui");
|
|
@@ -8911,8 +9003,8 @@ function BillingContent({
|
|
|
8911
9003
|
toast.success("Plan update submitted");
|
|
8912
9004
|
await fetchBillingOverview();
|
|
8913
9005
|
} catch (err) {
|
|
8914
|
-
const message = err
|
|
8915
|
-
const shouldCreateWorkspace =
|
|
9006
|
+
const message = errorMessage(err, { method: "POST" });
|
|
9007
|
+
const shouldCreateWorkspace = isBillingWorkspaceMissing(err);
|
|
8916
9008
|
if (shouldCreateWorkspace) {
|
|
8917
9009
|
const created = await ensureWorkspaceOnBilling();
|
|
8918
9010
|
if (created && api.updateSubscription) {
|
|
@@ -8965,7 +9057,7 @@ function BillingContent({
|
|
|
8965
9057
|
toast.error("Unable to cancel downgrade");
|
|
8966
9058
|
}
|
|
8967
9059
|
} catch (err) {
|
|
8968
|
-
const msg = err
|
|
9060
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
8969
9061
|
toast.error(msg);
|
|
8970
9062
|
} finally {
|
|
8971
9063
|
setPlanActionInFlight(null);
|
|
@@ -9156,7 +9248,7 @@ function BillingContent({
|
|
|
9156
9248
|
setShowBuyCreditsModal(false);
|
|
9157
9249
|
await fetchBillingOverview();
|
|
9158
9250
|
} catch (err) {
|
|
9159
|
-
const message = err
|
|
9251
|
+
const message = errorMessage(err, { method: "POST" });
|
|
9160
9252
|
toast.error(message);
|
|
9161
9253
|
} finally {
|
|
9162
9254
|
setBuyCreditsInFlight(false);
|
|
@@ -9487,7 +9579,7 @@ function CreateTokenModal({ onClose, onCreated }) {
|
|
|
9487
9579
|
const data = await api.createToken({ name: name.trim(), expiry });
|
|
9488
9580
|
onCreated(data);
|
|
9489
9581
|
} catch (err) {
|
|
9490
|
-
toast.error(err
|
|
9582
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
9491
9583
|
} finally {
|
|
9492
9584
|
setLoading(false);
|
|
9493
9585
|
}
|
|
@@ -9842,7 +9934,7 @@ function TokensContent({
|
|
|
9842
9934
|
setTokens((prev) => prev.filter((t) => t._id !== tokenId));
|
|
9843
9935
|
}
|
|
9844
9936
|
} catch (err) {
|
|
9845
|
-
toast.error(err
|
|
9937
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
9846
9938
|
} finally {
|
|
9847
9939
|
setDeletingId(null);
|
|
9848
9940
|
}
|
|
@@ -9854,7 +9946,7 @@ function TokensContent({
|
|
|
9854
9946
|
toast.success("Token permanently deleted.");
|
|
9855
9947
|
setTokens((prev) => prev.filter((t) => t._id !== tokenId));
|
|
9856
9948
|
} catch (err) {
|
|
9857
|
-
toast.error(err
|
|
9949
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
9858
9950
|
} finally {
|
|
9859
9951
|
setDeletingId(null);
|
|
9860
9952
|
}
|
|
@@ -10692,7 +10784,7 @@ function ProfileTab() {
|
|
|
10692
10784
|
await auth.refreshProfile();
|
|
10693
10785
|
toast.success("Profile updated");
|
|
10694
10786
|
} catch (err) {
|
|
10695
|
-
const msg = err
|
|
10787
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
10696
10788
|
toast.error(msg);
|
|
10697
10789
|
} finally {
|
|
10698
10790
|
setSaving(false);
|
|
@@ -10725,7 +10817,7 @@ function ProfileTab() {
|
|
|
10725
10817
|
toast.success("Profile image updated");
|
|
10726
10818
|
} catch (err) {
|
|
10727
10819
|
setImagePreview(void 0);
|
|
10728
|
-
const msg = err
|
|
10820
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
10729
10821
|
toast.error(msg);
|
|
10730
10822
|
} finally {
|
|
10731
10823
|
URL.revokeObjectURL(localPreviewUrl);
|
|
@@ -10745,7 +10837,7 @@ function ProfileTab() {
|
|
|
10745
10837
|
await auth.refreshProfile();
|
|
10746
10838
|
toast.success("Profile image removed");
|
|
10747
10839
|
} catch (err) {
|
|
10748
|
-
const msg = err
|
|
10840
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
10749
10841
|
toast.error(msg);
|
|
10750
10842
|
} finally {
|
|
10751
10843
|
setImageSaving(false);
|
|
@@ -11036,9 +11128,9 @@ function groupWorkspaceList(workspaces, organizations = []) {
|
|
|
11036
11128
|
});
|
|
11037
11129
|
}
|
|
11038
11130
|
}
|
|
11039
|
-
const
|
|
11131
|
+
const known2 = new Set(organizations.map((org) => org._id));
|
|
11040
11132
|
const ungrouped = workspaces.filter(
|
|
11041
|
-
(ws) => !ws.organizationId || !
|
|
11133
|
+
(ws) => !ws.organizationId || !known2.has(ws.organizationId)
|
|
11042
11134
|
);
|
|
11043
11135
|
if (ungrouped.length) {
|
|
11044
11136
|
groups.push({
|
|
@@ -11589,17 +11681,6 @@ function SettingsContentInner({
|
|
|
11589
11681
|
imageRemoved
|
|
11590
11682
|
});
|
|
11591
11683
|
};
|
|
11592
|
-
const getErrorMessage = (err, fallback) => {
|
|
11593
|
-
if (err instanceof Error && err.message.trim()) return err.message;
|
|
11594
|
-
if (err && typeof err === "object" && "body" in err && err.body && typeof err.body === "object" && "status" in err.body && err.body.status && typeof err.body.status === "object" && "message" in err.body.status && typeof err.body.status.message === "string") {
|
|
11595
|
-
return err.body.status.message;
|
|
11596
|
-
}
|
|
11597
|
-
return fallback;
|
|
11598
|
-
};
|
|
11599
|
-
const isSingleAdminError = (message) => {
|
|
11600
|
-
const normalized = message.toLowerCase();
|
|
11601
|
-
return normalized.includes("single admin") || normalized.includes("only admin");
|
|
11602
|
-
};
|
|
11603
11684
|
const getSettingsPath = (nextWorkspaceId) => `/dashboard/${nextWorkspaceId}/settings`;
|
|
11604
11685
|
const getNextWorkspaceId = async (excludedWorkspaceId) => {
|
|
11605
11686
|
try {
|
|
@@ -11683,7 +11764,7 @@ function SettingsContentInner({
|
|
|
11683
11764
|
toast.success("Workspace updated");
|
|
11684
11765
|
return true;
|
|
11685
11766
|
} catch (err) {
|
|
11686
|
-
toast.error(
|
|
11767
|
+
toast.error(errorMessage(err, { method: "PATCH" }));
|
|
11687
11768
|
return false;
|
|
11688
11769
|
} finally {
|
|
11689
11770
|
setUpdatingWorkspace(false);
|
|
@@ -11751,7 +11832,7 @@ function SettingsContentInner({
|
|
|
11751
11832
|
toast.success("Workspace created");
|
|
11752
11833
|
return true;
|
|
11753
11834
|
} catch (err) {
|
|
11754
|
-
const msg = err
|
|
11835
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
11755
11836
|
toast.error(msg);
|
|
11756
11837
|
return false;
|
|
11757
11838
|
} finally {
|
|
@@ -11798,7 +11879,7 @@ function SettingsContentInner({
|
|
|
11798
11879
|
toast.success("Workspace updated");
|
|
11799
11880
|
return true;
|
|
11800
11881
|
} catch (err) {
|
|
11801
|
-
const msg = err
|
|
11882
|
+
const msg = errorMessage(err, { method: "POST" });
|
|
11802
11883
|
toast.error(msg);
|
|
11803
11884
|
return false;
|
|
11804
11885
|
} finally {
|
|
@@ -12274,11 +12355,10 @@ function SettingsContentInner({
|
|
|
12274
12355
|
setLeavingWorkspace(null);
|
|
12275
12356
|
await completeWorkspaceRemoval(wsId, `You left ${wsName}`);
|
|
12276
12357
|
} catch (err) {
|
|
12277
|
-
|
|
12278
|
-
if (isSingleAdminError(message)) {
|
|
12358
|
+
if (isOnlyWorkspaceAdmin(err)) {
|
|
12279
12359
|
toast.error("You are the only admin. Promote another admin before leaving.");
|
|
12280
12360
|
} else {
|
|
12281
|
-
toast.error(
|
|
12361
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
12282
12362
|
}
|
|
12283
12363
|
}
|
|
12284
12364
|
},
|
|
@@ -12308,7 +12388,7 @@ function SettingsContentInner({
|
|
|
12308
12388
|
setDeletingWorkspace(null);
|
|
12309
12389
|
await completeWorkspaceRemoval(wsId, `Workspace ${wsName} deleted`);
|
|
12310
12390
|
} catch (err) {
|
|
12311
|
-
toast.error(
|
|
12391
|
+
toast.error(errorMessage(err, { method: "DELETE" }));
|
|
12312
12392
|
}
|
|
12313
12393
|
}
|
|
12314
12394
|
}
|