refactor(config): make EditorState/ConfirmDeleteState generic over the artifact type
Review feedback: string widening dropped the compile-time guard at the write/delete boundary right where the Codex panel (the next task) starts writing into this state. Threading <TType extends string = CcArtifactType> through EditorState/EditorModal and ConfirmDeleteState/ConfirmDeleteModal keeps CcConfig.tsx's write/delete calls checked against CcArtifactType by default while still letting a Codex-typed caller instantiate its own union later, removing the two `as CcArtifactType` casts.
This commit is contained in:
@@ -9,22 +9,27 @@
|
|||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { ShieldAlert, Trash2 } from "lucide-react";
|
import { ShieldAlert, Trash2 } from "lucide-react";
|
||||||
|
import type { CcArtifactType } from "../../lib/api";
|
||||||
|
|
||||||
export type ConfirmDeleteState = {
|
export type ConfirmDeleteState<TType extends string = CcArtifactType> = {
|
||||||
type: string;
|
type: TType;
|
||||||
scope: "user" | "project" | "auto-memory";
|
scope: "user" | "project" | "auto-memory";
|
||||||
name?: string;
|
name?: string;
|
||||||
path: string;
|
path: string;
|
||||||
project?: string; // set for type === "auto-memory"
|
project?: string; // set for type === "auto-memory"
|
||||||
} | null;
|
} | null;
|
||||||
|
|
||||||
interface ConfirmDeleteModalProps {
|
interface ConfirmDeleteModalProps<TType extends string = CcArtifactType> {
|
||||||
state: NonNullable<ConfirmDeleteState>;
|
state: NonNullable<ConfirmDeleteState<TType>>;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
onConfirm: () => Promise<void>;
|
onConfirm: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ConfirmDeleteModal({ state, onCancel, onConfirm }: ConfirmDeleteModalProps) {
|
export function ConfirmDeleteModal<TType extends string = CcArtifactType>({
|
||||||
|
state,
|
||||||
|
onCancel,
|
||||||
|
onConfirm,
|
||||||
|
}: ConfirmDeleteModalProps<TType>) {
|
||||||
const { t } = useTranslation("ccConfig");
|
const { t } = useTranslation("ccConfig");
|
||||||
const [busy, setBusy] = useState(false);
|
const [busy, setBusy] = useState(false);
|
||||||
|
|
||||||
|
|||||||
@@ -10,18 +10,19 @@
|
|||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Pencil, X, Save, AlertCircle } from "lucide-react";
|
import { Pencil, X, Save, AlertCircle } from "lucide-react";
|
||||||
|
import type { CcArtifactType } from "../../lib/api";
|
||||||
|
|
||||||
export type EditorState =
|
export type EditorState<TType extends string = CcArtifactType> =
|
||||||
| {
|
| {
|
||||||
mode: "create";
|
mode: "create";
|
||||||
type: string;
|
type: TType;
|
||||||
defaultScope: "user" | "project";
|
defaultScope: "user" | "project";
|
||||||
template: string;
|
template: string;
|
||||||
project?: string; // set for type === "auto-memory"
|
project?: string; // set for type === "auto-memory"
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
mode: "edit";
|
mode: "edit";
|
||||||
type: string;
|
type: TType;
|
||||||
scope: "user" | "project" | "auto-memory";
|
scope: "user" | "project" | "auto-memory";
|
||||||
name: string;
|
name: string;
|
||||||
filePath: string;
|
filePath: string;
|
||||||
@@ -29,12 +30,12 @@ export type EditorState =
|
|||||||
}
|
}
|
||||||
| null;
|
| null;
|
||||||
|
|
||||||
interface EditorModalProps {
|
interface EditorModalProps<TType extends string = CcArtifactType> {
|
||||||
state: NonNullable<EditorState>;
|
state: NonNullable<EditorState<TType>>;
|
||||||
fetchContent: (filePath: string) => Promise<string>;
|
fetchContent: (filePath: string) => Promise<string>;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onSave: (args: {
|
onSave: (args: {
|
||||||
type: string;
|
type: TType;
|
||||||
targetScope: "user" | "project" | "auto-memory";
|
targetScope: "user" | "project" | "auto-memory";
|
||||||
name: string | undefined;
|
name: string | undefined;
|
||||||
content: string;
|
content: string;
|
||||||
@@ -42,7 +43,12 @@ interface EditorModalProps {
|
|||||||
}) => Promise<void>;
|
}) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EditorModal({ state, fetchContent, onClose, onSave }: EditorModalProps) {
|
export function EditorModal<TType extends string = CcArtifactType>({
|
||||||
|
state,
|
||||||
|
fetchContent,
|
||||||
|
onClose,
|
||||||
|
onSave,
|
||||||
|
}: EditorModalProps<TType>) {
|
||||||
const { t } = useTranslation("ccConfig");
|
const { t } = useTranslation("ccConfig");
|
||||||
const isCreate = state.mode === "create";
|
const isCreate = state.mode === "create";
|
||||||
const isAutoMemory = state.type === "auto-memory";
|
const isAutoMemory = state.type === "auto-memory";
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ export function CcConfig() {
|
|||||||
|
|
||||||
const handleSave = useCallback(
|
const handleSave = useCallback(
|
||||||
async (args: {
|
async (args: {
|
||||||
type: string;
|
type: CcArtifactType;
|
||||||
targetScope: "user" | "project" | "auto-memory";
|
targetScope: "user" | "project" | "auto-memory";
|
||||||
name: string | undefined;
|
name: string | undefined;
|
||||||
content: string;
|
content: string;
|
||||||
@@ -434,7 +434,7 @@ export function CcConfig() {
|
|||||||
}) => {
|
}) => {
|
||||||
const result: CcMutationResult = await api.ccConfig.write({
|
const result: CcMutationResult = await api.ccConfig.write({
|
||||||
scope: args.targetScope,
|
scope: args.targetScope,
|
||||||
type: args.type as CcArtifactType,
|
type: args.type,
|
||||||
name: args.name,
|
name: args.name,
|
||||||
content: args.content,
|
content: args.content,
|
||||||
project: args.project,
|
project: args.project,
|
||||||
@@ -456,7 +456,7 @@ export function CcConfig() {
|
|||||||
try {
|
try {
|
||||||
const result = await api.ccConfig.delete({
|
const result = await api.ccConfig.delete({
|
||||||
scope: confirmDelete.scope,
|
scope: confirmDelete.scope,
|
||||||
type: confirmDelete.type as CcArtifactType,
|
type: confirmDelete.type,
|
||||||
name: confirmDelete.name,
|
name: confirmDelete.name,
|
||||||
project: confirmDelete.project,
|
project: confirmDelete.project,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user