From bff92086f5f150a37307bf21a2515ba940db5d0f Mon Sep 17 00:00:00 2001 From: ryoppippi <1560508+ryoppippi@users.noreply.github.com> Date: Tue, 9 Dec 2025 14:27:31 +0000 Subject: [PATCH] refactor(rpc): extract RPC schemas to dedicated schema file Move Zod schemas and their inferred types from rpc-client.ts to a new src/schemas/rpc.ts file for improved separation of concerns. Changes: - Create src/schemas/rpc.ts with exported schemas and types: - rpcActionRequestSchema/RpcActionRequest - rpcActionResponseSchema/RpcActionResponse - rpcClientConfigSchema/RpcClientConfig - Update rpc-client.ts to import schemas from new location - Add explicit type annotation to actions property for type portability - Keep rpcActionResponseDataSchema as internal (not exported) - Re-export RpcActionResponse from rpc-client.ts for consumers Benefits: - Schema definitions are separate from RpcClient implementation - Schemas can be imported independently without bringing in RpcClient - Schemas can be tested in isolation - Schema file serves as clear API contract reference Closes #171 --- src/rpc-client.ts | 79 ++++++++-------------------------------------- src/schemas/rpc.ts | 66 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 66 deletions(-) create mode 100644 src/schemas/rpc.ts diff --git a/src/rpc-client.ts b/src/rpc-client.ts index 8607a87b..7cd0621b 100644 --- a/src/rpc-client.ts +++ b/src/rpc-client.ts @@ -1,70 +1,15 @@ -import { z } from 'zod'; +import { + type RpcActionRequest, + type RpcActionResponse, + type RpcClientConfig, + rpcActionRequestSchema, + rpcActionResponseSchema, + rpcClientConfigSchema, +} from './schemas/rpc'; import { StackOneAPIError } from './utils/errors'; -/** - * Zod schema for RPC action request validation - * @see https://docs.stackone.com/platform/api-reference/actions/make-an-rpc-call-to-an-action - */ -const rpcActionRequestSchema = z.object({ - action: z.string(), - body: z.record(z.unknown()).optional(), - headers: z.record(z.unknown()).optional(), - path: z.record(z.unknown()).optional(), - query: z.record(z.unknown()).optional(), -}); - -/** - * RPC action request payload - */ -type RpcActionRequest = z.infer; - -/** - * Zod schema for RPC action response data - */ -const rpcActionResponseDataSchema = z.union([ - z.record(z.unknown()), - z.array(z.record(z.unknown())), - z.null(), -]); - -/** - * Zod schema for RPC action response validation - * - * The server returns a flexible JSON structure. Known fields: - * - `data`: The main response data (object, array, or null) - * - `next`: Pagination cursor for fetching next page - * - * Additional fields from the connector response are passed through. - * @see unified-cloud-api/src/unified-api-v2/unifiedAPIv2.service.ts processActionCall - */ -const rpcActionResponseSchema = z - .object({ - next: z.string().nullish(), - data: rpcActionResponseDataSchema.optional(), - }) - .passthrough(); - -/** - * RPC action response from the StackOne API - * Contains known fields (data, next) plus any additional fields from the connector - */ -export type RpcActionResponse = z.infer; - -/** - * Zod schema for RPC client configuration validation - */ -const rpcClientConfigSchema = z.object({ - serverURL: z.string().optional(), - security: z.object({ - username: z.string(), - password: z.string().optional(), - }), -}); - -/** - * Configuration for the RPC client - */ -type RpcClientConfig = z.infer; +// Re-export types for consumers and to make types portable +export type { RpcActionResponse } from './schemas/rpc'; /** * Custom RPC client for StackOne API. @@ -88,7 +33,9 @@ export class RpcClient { /** * Actions namespace containing RPC methods */ - readonly actions = { + readonly actions: { + rpcAction: (request: RpcActionRequest) => Promise; + } = { /** * Execute an RPC action * @param request The RPC action request diff --git a/src/schemas/rpc.ts b/src/schemas/rpc.ts new file mode 100644 index 00000000..78a7ce3c --- /dev/null +++ b/src/schemas/rpc.ts @@ -0,0 +1,66 @@ +import { z } from 'zod'; + +/** + * Zod schema for RPC action request validation + * @see https://docs.stackone.com/platform/api-reference/actions/make-an-rpc-call-to-an-action + */ +export const rpcActionRequestSchema = z.object({ + action: z.string(), + body: z.record(z.unknown()).optional(), + headers: z.record(z.unknown()).optional(), + path: z.record(z.unknown()).optional(), + query: z.record(z.unknown()).optional(), +}); + +/** + * RPC action request payload + */ +export type RpcActionRequest = z.infer; + +/** + * Zod schema for RPC action response data + */ +const rpcActionResponseDataSchema = z.union([ + z.record(z.unknown()), + z.array(z.record(z.unknown())), + z.null(), +]); + +/** + * Zod schema for RPC action response validation + * + * The server returns a flexible JSON structure. Known fields: + * - `data`: The main response data (object, array, or null) + * - `next`: Pagination cursor for fetching next page + * + * Additional fields from the connector response are passed through. + * @see unified-cloud-api/src/unified-api-v2/unifiedAPIv2.service.ts processActionCall + */ +export const rpcActionResponseSchema = z + .object({ + next: z.string().nullish(), + data: rpcActionResponseDataSchema.optional(), + }) + .passthrough(); + +/** + * RPC action response from the StackOne API + * Contains known fields (data, next) plus any additional fields from the connector + */ +export type RpcActionResponse = z.infer; + +/** + * Zod schema for RPC client configuration validation + */ +export const rpcClientConfigSchema = z.object({ + serverURL: z.string().optional(), + security: z.object({ + username: z.string(), + password: z.string().optional(), + }), +}); + +/** + * Configuration for the RPC client + */ +export type RpcClientConfig = z.infer;