MCPcopy Create free account
hub / github.com/ShipSecAI/studio / validateComponentSchema

Function validateComponentSchema

packages/component-sdk/src/schema-validation.ts:62–135  ·  view source on GitHub ↗
(
  schema: z.ZodTypeAny,
  options: ValidationOptions = {}
)

Source from the content-addressed store, hash-verified

60 * @returns Validation result with any errors found
61 */
62export function validateComponentSchema(
63 schema: z.ZodTypeAny,
64 options: ValidationOptions = {}
65): SchemaValidationResult {
66 const errors: string[] = [];
67 const objectSchema = unwrapToObject(schema);
68 if (!objectSchema) {
69 return { valid: true, errors };
70 }
71 const shape = getObjectShape(objectSchema);
72
73 for (const [fieldName, fieldSchema] of Object.entries(shape)) {
74 const typedSchema = fieldSchema as z.ZodTypeAny;
75 const portMeta = getPortMeta(typedSchema);
76 if (!portMeta) {
77 continue;
78 }
79 try {
80 deriveConnectionType(typedSchema);
81 } catch (error) {
82 errors.push(
83 `Field "${fieldName}": ${error instanceof Error ? error.message : String(error)}`,
84 );
85 }
86
87 // Rule: Require label or default to field name
88 if (!portMeta?.label) {
89 // OK - will default to field name in extractPorts
90 }
91
92 // Rule: Block z.any()/z.unknown() without explicit allowAny
93 const unwrapped = unwrapEffects(typedSchema);
94 if (isAnyOrUnknown(unwrapped) && !portMeta?.allowAny) {
95 errors.push(
96 `Field "${fieldName}": z.any() or z.unknown() requires explicit meta.allowAny=true${portMeta?.reason ? ` (${portMeta.reason})` : ''}`
97 );
98 }
99
100 // Rule: If allowAny is set, require reason
101 if (portMeta?.allowAny && !portMeta?.reason) {
102 errors.push(`Field "${fieldName}": meta.allowAny=true requires meta.reason explaining why`);
103 }
104
105 // Rule: Check depth limit (default 1 level)
106 if (options.maxDepth !== undefined) {
107 const depth = calculateDepth(typedSchema);
108 if (depth > options.maxDepth) {
109 errors.push(
110 `Field "${fieldName}": Nesting depth ${depth} exceeds max depth ${options.maxDepth}. Use meta.connectionType for complex nested types.`
111 );
112 }
113 }
114
115 // Rule: If schemaName is set, it's a contract export
116 if (portMeta?.schemaName) {
117 // OK - explicit contract export
118 }
119

Callers 2

registerMethod · 0.90
port-meta.test.tsFile · 0.90

Calls 9

getPortMetaFunction · 0.90
deriveConnectionTypeFunction · 0.90
isAnyOrUnknownFunction · 0.85
calculateDepthFunction · 0.85
isUnionTypeFunction · 0.85
unwrapToObjectFunction · 0.70
getObjectShapeFunction · 0.70
unwrapEffectsFunction · 0.70
pushMethod · 0.65

Tested by

no test coverage detected