import chalk from 'chalk'; import { NetworkProductModuleDefinitionRequest } from '../domain/product-module-definition'; import { PlatformError } from '../errors/platform-error'; import { HttpMethod, RootAPIHelper } from './root-api'; /** * Send the product module definition to platform to be validated */ export const validateProductModuleDefinition = async (params: { productModuleKey: string; apiKey: string; productModuleDefinition: NetworkProductModuleDefinitionRequest; host: string; }) => { const { apiKey, host, productModuleDefinition, productModuleKey } = params; const rootApi = new RootAPIHelper({ host, apiKey, throwResponseErrors: true }); const path = `/cli/product-modules/${productModuleKey}`; const searchParams = { validate_only: 'true' }; try { await rootApi.send({ method: HttpMethod.Post, path, body: productModuleDefinition, searchParams }); } catch (error) { // Only wrap genuine validation rejections from the platform. NetworkError (DNS, // connection refused, fetch failed, timeout) and non-validation PlatformErrors // (5xx, auth, rate-limit) re-throw unchanged so the top-level handler in // src/index.ts renders them with their native "Network Error" / "API Error" // framing — and we don't tell the user to "review the validation errors above" // when no validation actually ran. const isValidationRejection = error instanceof PlatformError && error.networkError?.error?.type === 'validation_error'; if (!isValidationRejection) { throw error; } throw new Error( [ `Platform rejected the product module definition`, `Module: ${chalk.yellow(productModuleKey)}`, '', 'Underlying error:', ...error.message.split('\n').map((line) => ` ${line}`), '', `Tip: review the validation errors above, fix the offending fields in your local product module, and run ${chalk.yellow( 'rp push', )} again.`, ].join('\n'), ); } };