import type {
Folder,
GrpcRequest,
HttpRequest,
InheritedBoolSetting,
InheritedIntSetting,
WebsocketRequest,
Workspace,
} from "@yaakapp-internal/models";
import { patchModel } from "@yaakapp-internal/models";
import { useModelAncestors } from "../hooks/useModelAncestors";
import { Checkbox } from "./core/Checkbox";
import { PlainInput } from "./core/PlainInput";
import {
SettingOverrideRow,
SettingRowBoolean,
SettingRowNumber,
SettingsList,
SettingsSection,
} from "./core/SettingRow";
interface Props {
showSectionTitles?: boolean;
model: ModelWithSettings;
}
type ModelWithSettings = Workspace | Folder | HttpRequest | WebsocketRequest | GrpcRequest;
type ModelWithHttpSettings = Workspace | Folder | HttpRequest;
type ModelWithCookieSettings = Workspace | Folder | HttpRequest | WebsocketRequest | GrpcRequest;
type BooleanSetting = boolean | InheritedBoolSetting;
type IntegerSetting = number | InheritedIntSetting;
type CookieSettingsPatch = {
settingSendCookies?: ModelWithCookieSettings["settingSendCookies"];
settingStoreCookies?: ModelWithCookieSettings["settingStoreCookies"];
};
type HttpSettingsPatch = {
settingValidateCertificates?: ModelWithHttpSettings["settingValidateCertificates"];
settingFollowRedirects?: ModelWithHttpSettings["settingFollowRedirects"];
settingRequestTimeout?: ModelWithHttpSettings["settingRequestTimeout"];
};
export function ModelSettingsEditor({ model, showSectionTitles = false }: Props) {
const ancestors = useModelAncestors(model);
const supportsHttpSettings =
model.model === "workspace" || model.model === "folder" || model.model === "http_request";
return (
{supportsHttpSettings && (
patchHttpSettings(model, {
settingRequestTimeout,
})
}
/>
patchHttpSettings(model, {
settingValidateCertificates,
})
}
/>
patchHttpSettings(model, {
settingFollowRedirects,
})
}
/>
)}
patchCookieSettings(model, {
settingSendCookies,
})
}
/>
patchCookieSettings(model, {
settingStoreCookies,
})
}
/>
);
}
export function countOverriddenSettings(model: ModelWithSettings) {
const settings: (BooleanSetting | IntegerSetting)[] = [
model.settingSendCookies,
model.settingStoreCookies,
];
if (model.model === "workspace" || model.model === "folder" || model.model === "http_request") {
settings.push(
model.settingValidateCertificates,
model.settingFollowRedirects,
model.settingRequestTimeout,
);
}
return settings.filter((setting) => isInheritedSetting(setting) && setting.enabled === true)
.length;
}
function patchCookieSettings(model: ModelWithCookieSettings, patch: Partial) {
if (model.model === "workspace") return patchModel(model, patch as Partial);
if (model.model === "folder") return patchModel(model, patch as Partial);
if (model.model === "http_request") return patchModel(model, patch as Partial);
if (model.model === "websocket_request")
return patchModel(model, patch as Partial);
return patchModel(model, patch as Partial);
}
function patchHttpSettings(model: ModelWithHttpSettings, patch: Partial) {
if (model.model === "workspace") return patchModel(model, patch as Partial);
if (model.model === "folder") return patchModel(model, patch as Partial);
return patchModel(model, patch as Partial);
}
function BooleanSettingRow({
description,
inheritedValue,
setting,
title,
onChange,
}: {
description: string;
inheritedValue: boolean;
setting: BooleanSetting;
title: string;
onChange: (setting: BooleanSetting) => void;
}) {
const inherited = isInheritedSetting(setting);
const overridden = inherited ? setting.enabled === true : false;
const value = inherited ? (overridden ? setting.value : inheritedValue) : setting;
if (!inherited) {
return (
onChange(value)}
/>
);
}
return (
onChange({ ...setting, enabled: false })}
>
onChange({ ...setting, enabled: true, value })}
/>
);
}
function IntegerSettingRow({
description,
inheritedValue,
name,
setting,
title,
onChange,
}: {
description: string;
inheritedValue: number;
name: string;
setting: IntegerSetting;
title: string;
onChange: (setting: IntegerSetting) => void;
}) {
const inherited = isInheritedSetting(setting);
const overridden = inherited ? setting.enabled === true : false;
const value = inherited ? (overridden ? setting.value : inheritedValue) : setting;
const showReset = overridden && value !== inheritedValue;
if (!inherited) {
return (
value === "" || Number.parseInt(value, 10) >= 0}
onChange={(value) => onChange(value)}
/>
);
}
return (
onChange({ ...setting, enabled: false })}
>
value === "" || Number.parseInt(value, 10) >= 0}
onChange={(value) =>
onChange({
...setting,
enabled: true,
value: Number.parseInt(value, 10) || 0,
})
}
/>
);
}
function isInheritedSetting(
setting: T | { enabled?: boolean; value: T },
): setting is { enabled?: boolean; value: T } {
return typeof setting === "object" && setting != null && "value" in setting;
}
function resolveInheritedValue(
ancestors: (Folder | Workspace)[],
key: "settingRequestTimeout",
fallback: IntegerSetting,
): number;
function resolveInheritedValue(
ancestors: (Folder | Workspace)[],
key: BooleanWorkspaceSettingKey,
fallback: BooleanSetting,
): boolean;
function resolveInheritedValue(
ancestors: (Folder | Workspace)[],
key: keyof WorkspaceSettings,
fallback: BooleanSetting | IntegerSetting,
) {
for (const ancestor of ancestors) {
const setting = ancestor[key] as BooleanSetting | IntegerSetting;
if (isInheritedSetting(setting)) {
if (setting.enabled === true) {
return setting.value;
}
continue;
}
return setting;
}
return isInheritedSetting(fallback) ? fallback.value : fallback;
}
type WorkspaceSettings = Pick<
Workspace,
| "settingFollowRedirects"
| "settingRequestTimeout"
| "settingSendCookies"
| "settingStoreCookies"
| "settingValidateCertificates"
>;
type BooleanWorkspaceSettingKey = Exclude;