fix: address release v2 review findings

This commit is contained in:
ajnart committed 2026-08-26 14:51:16 +02:00
1 parent f0eddda573
commit 16e437decc
35 files changed
+587 -258

No files matched your search

@@ -12,6 +12,11 @@ describe("getUsableWidgetQueryData", () => {
expect(getUsableWidgetQueryData({ data, error: new Error("offline") })).toBe(data);
});
test("throws access-denied refetches instead of rendering stale cached data", () => {
const error = { data: { code: "FORBIDDEN" } };
expect(() => getUsableWidgetQueryData({ data: [{ id: "revoked" }], error })).toThrow(error);
});
test("throws a terminal failure when no usable data exists", () => {
const error = new Error("offline");
expect(() => getUsableWidgetQueryData({ data: undefined, error })).toThrow(error);
@@ -7,8 +7,20 @@ interface PendingWidgetQueryState extends WidgetQueryState {
isPending: boolean;
}
const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === "object" && value !== null;
interface ForbiddenTrpcError {
data: { code: "FORBIDDEN" };
}
export const isTrpcForbiddenError = (error: unknown): error is ForbiddenTrpcError => {
if (!isRecord(error) || !isRecord(error.data)) return false;
return error.data.code === "FORBIDDEN";
};
/** Throws terminal query failures while preserving successful empty values and stale cached data. */
export const getUsableWidgetQueryData = <TQuery extends WidgetQueryState>(query: TQuery): TQuery["data"] => {
if (isTrpcForbiddenError(query.error)) throw query.error;
if (query.error && query.data === undefined) throw query.error;
return query.data;
};
@@ -63,10 +63,14 @@ export interface WidgetEditModalSize {
height: number;
}
export interface WidgetPreviewDimensions extends WidgetEditModalSize {
scale?: number;
}
interface WidgetEditPreviewResizeOptions {
initialSize: WidgetEditModalSize;
maximumSize: WidgetEditModalSize;
getDimensions?: (size: WidgetEditModalSize) => { width: number; height: number; scale?: number };
getDimensions?: (size: WidgetEditModalSize) => WidgetPreviewDimensions;
}
export interface EmbeddedIntegrationEditFormHandle {
@@ -94,7 +98,7 @@ export interface WidgetEditModalProps<TSort extends WidgetKind> {
onIntegrationSaved?: () => void;
onOpenNewIntegration?: (onCreated?: (id: string) => void) => void;
previewComponent?: ComponentType<WidgetComponentProps<TSort>>;
previewDimensions?: { width: number; height: number; scale?: number };
previewDimensions?: WidgetPreviewDimensions;
previewResize?: WidgetEditPreviewResizeOptions;
previewWrapper?: ComponentType<PropsWithChildren>;
}
@@ -106,7 +110,7 @@ interface WidgetEditPreviewProps {
state: WidgetEditModalState;
itemId?: string;
boardId?: string;
dimensions?: { width: number; height: number; scale?: number };
dimensions?: WidgetPreviewDimensions;
integrationData: IntegrationSelectOption[];
onChangeOptions: (newOptions: Record<string, unknown>) => void;
resize?: {
@@ -174,7 +178,9 @@ const WidgetEditPreview = ({
},
}));
let componentItemId = itemId;
if (kind === "assistant") componentItemId = `widget-preview-${generatedPreviewId}`;
if (kind === "assistant" || kind === "timer") {
componentItemId = `widget-preview-${generatedPreviewId}`;
}
const isPendingCustomWidget = kind === "customApi" && !itemId;
const previewOpacity = (board?.opacity ?? 100) / 100;
const handleResizeValue = (dimension: keyof WidgetEditModalSize, value: string | number) => {