Skip to content

Commit 56eadf3

Browse files
committed
refactor: share approval resolve param parsing
1 parent 912f663 commit 56eadf3

3 files changed

Lines changed: 65 additions & 40 deletions

File tree

src/gateway/server-methods/approval-shared.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { ErrorCodes, errorShape } from "../../../packages/gateway-protocol/src/index.js";
1+
import {
2+
ErrorCodes,
3+
errorShape,
4+
formatValidationErrors,
5+
} from "../../../packages/gateway-protocol/src/index.js";
6+
import type { ValidationError } from "../../../packages/gateway-protocol/src/index.js";
27
import { hasApprovalTurnSourceRoute } from "../../infra/approval-turn-source.js";
38
import type { ExecApprovalDecision } from "../../infra/exec-approvals.js";
49
import { normalizeOptionalString } from "../../shared/string-coerce.js";
@@ -51,6 +56,17 @@ type PendingApprovalListEntry<TPayload> = {
5156
expiresAtMs: number;
5257
};
5358

59+
type ApprovalResolveParams = {
60+
id: string;
61+
decision: string;
62+
};
63+
64+
type ApprovalResolveParamsValidator<TParams extends ApprovalResolveParams> = ((
65+
params: unknown,
66+
) => params is TParams) & {
67+
errors?: ValidationError[] | null;
68+
};
69+
5470
function isPromiseLike<T>(value: T | Promise<T>): value is Promise<T> {
5571
return typeof value === "object" && value !== null && "then" in value;
5672
}
@@ -180,6 +196,34 @@ export function buildRequestedApprovalEvent<TPayload extends ApprovalTurnSourceF
180196
};
181197
}
182198

199+
export function resolveApprovalDecisionParams<TParams extends ApprovalResolveParams>(params: {
200+
rawParams: unknown;
201+
validate: ApprovalResolveParamsValidator<TParams>;
202+
methodName: string;
203+
respond: RespondFn;
204+
}): { inputId: string; decision: ExecApprovalDecision } | null {
205+
const rawParams = params.rawParams;
206+
if (!params.validate(rawParams)) {
207+
params.respond(
208+
false,
209+
undefined,
210+
errorShape(
211+
ErrorCodes.INVALID_REQUEST,
212+
`invalid ${params.methodName} params: ${formatValidationErrors(params.validate.errors)}`,
213+
),
214+
);
215+
return null;
216+
}
217+
if (!isApprovalDecision(rawParams.decision)) {
218+
params.respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "invalid decision"));
219+
return null;
220+
}
221+
return {
222+
inputId: rawParams.id,
223+
decision: rawParams.decision,
224+
};
225+
}
226+
183227
export function resolveApprovalRequestRecipientConnIds<TPayload>(params: {
184228
context: GatewayRequestContext;
185229
record: ExecApprovalRecord<TPayload>;

src/gateway/server-methods/exec-approval.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import {
2020
DEFAULT_EXEC_APPROVAL_TIMEOUT_MS,
2121
resolveExecApprovalAllowedDecisions,
2222
resolveExecApprovalRequestAllowedDecisions,
23-
type ExecApprovalDecision,
2423
type ExecApprovalRequest,
2524
type ExecApprovalResolved,
2625
} from "../../infra/exec-approvals.js";
@@ -37,10 +36,10 @@ import {
3736
bindApprovalRequesterMetadata,
3837
buildRequestedApprovalEvent,
3938
handleApprovalResolve,
40-
isApprovalDecision,
4139
isApprovalRecordVisibleToClient,
4240
listVisiblePendingApprovalRequests,
4341
registerPendingApprovalRecord,
42+
resolveApprovalDecisionParams,
4443
respondPendingApprovalLookupError,
4544
resolvePendingApprovalRecord,
4645
} from "./approval-shared.js";
@@ -416,28 +415,19 @@ export function createExecApprovalHandlers(
416415
});
417416
},
418417
"exec.approval.resolve": async ({ params, respond, client, context }) => {
419-
if (!validateExecApprovalResolveParams(params)) {
420-
respond(
421-
false,
422-
undefined,
423-
errorShape(
424-
ErrorCodes.INVALID_REQUEST,
425-
`invalid exec.approval.resolve params: ${formatValidationErrors(
426-
validateExecApprovalResolveParams.errors,
427-
)}`,
428-
),
429-
);
430-
return;
431-
}
432-
const p = params as { id: string; decision: string };
433-
if (!isApprovalDecision(p.decision)) {
434-
respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "invalid decision"));
418+
const resolveParams = resolveApprovalDecisionParams({
419+
rawParams: params,
420+
validate: validateExecApprovalResolveParams,
421+
methodName: "exec.approval.resolve",
422+
respond,
423+
});
424+
if (!resolveParams) {
435425
return;
436426
}
437-
const decision: ExecApprovalDecision = p.decision;
427+
const { inputId, decision } = resolveParams;
438428
await handleApprovalResolve({
439429
manager,
440-
inputId: p.id,
430+
inputId,
441431
decision,
442432
respond,
443433
context,

src/gateway/server-methods/plugin-approval.ts

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ import {
2121
handleApprovalResolve,
2222
handleApprovalWaitDecision,
2323
handlePendingApprovalRequest,
24-
isApprovalDecision,
2524
listVisiblePendingApprovalRequests,
2625
registerPendingApprovalRecord,
26+
resolveApprovalDecisionParams,
2727
} from "./approval-shared.js";
2828
import type { GatewayRequestHandlers } from "./types.js";
2929

@@ -147,28 +147,19 @@ export function createPluginApprovalHandlers(
147147
},
148148

149149
"plugin.approval.resolve": async ({ params, respond, client, context }) => {
150-
if (!validatePluginApprovalResolveParams(params)) {
151-
respond(
152-
false,
153-
undefined,
154-
errorShape(
155-
ErrorCodes.INVALID_REQUEST,
156-
`invalid plugin.approval.resolve params: ${formatValidationErrors(
157-
validatePluginApprovalResolveParams.errors,
158-
)}`,
159-
),
160-
);
161-
return;
162-
}
163-
const p = params as { id: string; decision: string };
164-
if (!isApprovalDecision(p.decision)) {
165-
respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "invalid decision"));
150+
const resolveParams = resolveApprovalDecisionParams({
151+
rawParams: params,
152+
validate: validatePluginApprovalResolveParams,
153+
methodName: "plugin.approval.resolve",
154+
respond,
155+
});
156+
if (!resolveParams) {
166157
return;
167158
}
168-
const decision = p.decision;
159+
const { inputId, decision } = resolveParams;
169160
await handleApprovalResolve({
170161
manager,
171-
inputId: p.id,
162+
inputId,
172163
decision,
173164
respond,
174165
context,

0 commit comments

Comments
 (0)