Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 13 additions & 64 deletions src/rpc-client.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,15 @@
import { z } from 'zod/mini';
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.optional(z.record(z.string(), z.unknown())),
headers: z.optional(z.record(z.string(), z.unknown())),
path: z.optional(z.record(z.string(), z.unknown())),
query: z.optional(z.record(z.string(), z.unknown())),
});

/**
* RPC action request payload
*/
type RpcActionRequest = z.infer<typeof rpcActionRequestSchema>;

/**
* Zod schema for RPC action response data
*/
const rpcActionResponseDataSchema = z.union([
z.record(z.string(), z.unknown()),
z.array(z.record(z.string(), 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.looseObject({
next: z.nullable(z.optional(z.string())),
data: z.optional(rpcActionResponseDataSchema),
});

/**
* RPC action response from the StackOne API
* Contains known fields (data, next) plus any additional fields from the connector
*/
export type RpcActionResponse = z.infer<typeof rpcActionResponseSchema>;

/**
* Zod schema for RPC client configuration validation
*/
const rpcClientConfigSchema = z.object({
serverURL: z.optional(z.string()),
security: z.object({
username: z.string(),
password: z.optional(z.string()),
}),
});

/**
* Configuration for the RPC client
*/
type RpcClientConfig = z.infer<typeof rpcClientConfigSchema>;
// Re-export types for consumers and to make types portable
export type { RpcActionResponse } from './schemas/rpc';

/**
* Custom RPC client for StackOne API.
Expand All @@ -86,7 +33,9 @@ export class RpcClient {
/**
* Actions namespace containing RPC methods
*/
readonly actions = {
readonly actions: {
rpcAction: (request: RpcActionRequest) => Promise<RpcActionResponse>;
} = {
/**
* Execute an RPC action
* @param request The RPC action request
Expand Down
64 changes: 64 additions & 0 deletions src/schemas/rpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { z } from 'zod/mini';

/**
* 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.optional(z.record(z.string(), z.unknown())),
headers: z.optional(z.record(z.string(), z.unknown())),
path: z.optional(z.record(z.string(), z.unknown())),
query: z.optional(z.record(z.string(), z.unknown())),
});

/**
* RPC action request payload
*/
export type RpcActionRequest = z.infer<typeof rpcActionRequestSchema>;

/**
* Zod schema for RPC action response data
*/
const rpcActionResponseDataSchema = z.union([
z.record(z.string(), z.unknown()),
z.array(z.record(z.string(), 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.looseObject({
next: z.nullable(z.optional(z.string())),
data: z.optional(rpcActionResponseDataSchema),
});

/**
* RPC action response from the StackOne API
* Contains known fields (data, next) plus any additional fields from the connector
*/
export type RpcActionResponse = z.infer<typeof rpcActionResponseSchema>;

/**
* Zod schema for RPC client configuration validation
*/
export const rpcClientConfigSchema = z.object({
serverURL: z.optional(z.string()),
security: z.object({
username: z.string(),
password: z.optional(z.string()),
}),
});

/**
* Configuration for the RPC client
*/
export type RpcClientConfig = z.infer<typeof rpcClientConfigSchema>;
Loading