docs(portal-shell): add implementation plan for data abstraction & GraphQL hardening
- Plan: 20 tasks across M1-M4 phases - Spec: fix useWidgetMutation destructure (object, not array)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -222,33 +222,38 @@ export function useAuditLogs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mutation(hook 形态,因为 useWidgetMutation 是 React Hook)
|
// Mutation(hook 形态,因为 useWidgetMutation 是 React Hook)
|
||||||
export function useCreateInvitationCode(): [
|
export function useCreateInvitationCode(): {
|
||||||
(input: CreateInvitationCodeInput) => Promise<InvitationCode>,
|
run: (input: CreateInvitationCodeInput) => Promise<InvitationCode>;
|
||||||
UseMutationResult,
|
loading: boolean;
|
||||||
] {
|
error: ApolloError | undefined;
|
||||||
const [run, result] = useWidgetMutation<
|
} {
|
||||||
|
const {
|
||||||
|
run: rawRun,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
} = useWidgetMutation<
|
||||||
CreateInvitationCodeMutation,
|
CreateInvitationCodeMutation,
|
||||||
CreateInvitationCodeMutationVariables
|
CreateInvitationCodeMutationVariables
|
||||||
>(CREATE_INVITATION_CODE_DOC);
|
>(CREATE_INVITATION_CODE_DOC);
|
||||||
|
|
||||||
const wrappedRun = async (
|
const run = async (
|
||||||
input: CreateInvitationCodeInput,
|
input: CreateInvitationCodeInput,
|
||||||
): Promise<InvitationCode> => {
|
): Promise<InvitationCode> => {
|
||||||
const { data } = await run({ input });
|
const data = await rawRun({ input });
|
||||||
if (!data?.createInvitationCode) {
|
if (!data?.createInvitationCode) {
|
||||||
throw new ApiError("Failed to create invitation code", "INTERNAL_ERROR");
|
throw new ApiError("Failed to create invitation code", "INTERNAL_ERROR");
|
||||||
}
|
}
|
||||||
return data.createInvitationCode;
|
return data.createInvitationCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
return [wrappedRun, result];
|
return { run, loading, error };
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**规范要点**:
|
**规范要点**:
|
||||||
|
|
||||||
- 查询返回**领域模型**(`ChildSummary[]`),不是 GraphQL 原始响应(`{ myChildren: [...] }`),避免 schema 形状泄漏
|
- 查询返回**领域模型**(`ChildSummary[]`),不是 GraphQL 原始响应(`{ myChildren: [...] }`),避免 schema 形状泄漏
|
||||||
- Mutation 包装为 hook,返回 `[wrappedRun, result]` 元组;`wrappedRun` 抛 `ApiError`,widget 在事件 handler 中 `try/catch`
|
- Mutation 包装为 hook,返回 `{ run, loading, error }` 对象(与 `useWidgetMutation` 返回形态一致);`run` 抛 `ApiError`,widget 在事件 handler 中 `try/catch`
|
||||||
- 命名:查询与 Mutation 都用 `use` 前缀(`useParentChildren`、`useCreateInvitationCode`、`useApproveLeave`),保持 React Hook 规范
|
- 命名:查询与 Mutation 都用 `use` 前缀(`useParentChildren`、`useCreateInvitationCode`、`useApproveLeave`),保持 React Hook 规范
|
||||||
- 文件名 `<domain>.ts`,函数名 `use<Entity>`(查询)/ `use<Action><Entity>`(Mutation)
|
- 文件名 `<domain>.ts`,函数名 `use<Entity>`(查询)/ `use<Action><Entity>`(Mutation)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user