Skip to main content
Glama

mcp-google-sheets

props-processor.ts7.62 kB
import { InputPropertyMap, PieceAuthProperty, PieceProperty, PiecePropertyMap, PropertyType, StaticPropsValue } from '@activepieces/pieces-framework' import { AUTHENTICATION_PROPERTY_NAME, isNil, isObject, PropertySettings } from '@activepieces/shared' import { z } from 'zod' import { processors } from './processors' import { arrayZipperProcessor } from './processors/array-zipper' type PropsValidationError = { [key: string]: string[] | PropsValidationError | PropsValidationError[] } export const propsProcessor = { applyProcessorsAndValidators: async ( resolvedInput: StaticPropsValue<PiecePropertyMap>, props: InputPropertyMap, auth: PieceAuthProperty | undefined, requireAuth: boolean, propertySettings: Record<string, PropertySettings>, ): Promise<{ processedInput: StaticPropsValue<PiecePropertyMap>, errors: PropsValidationError }> => { let dynamaicPropertiesSchema: Record<string, InputPropertyMap> | undefined = undefined if (Object.keys(propertySettings).length > 0) { dynamaicPropertiesSchema = Object.fromEntries(Object.entries(propertySettings).map(([key, propertySetting]) => [key, propertySetting.schema])) } const processedInput = { ...resolvedInput } const errors: PropsValidationError = {} const isAuthenticationProperty = auth && (auth.type === PropertyType.CUSTOM_AUTH || auth.type === PropertyType.OAUTH2) && !isNil(auth.props) && requireAuth if (isAuthenticationProperty) { const { processedInput: authProcessedInput, errors: authErrors } = await propsProcessor.applyProcessorsAndValidators( resolvedInput[AUTHENTICATION_PROPERTY_NAME], auth.props, undefined, requireAuth, {}, ) processedInput.auth = authProcessedInput if (Object.keys(authErrors).length > 0) { errors.auth = authErrors } } for (const [key, value] of Object.entries(resolvedInput)) { const property = props[key] if (isNil(property)) { continue } if (property.type === PropertyType.DYNAMIC && !isNil(dynamaicPropertiesSchema?.[key])) { const { processedInput: itemProcessedInput, errors: itemErrors } = await propsProcessor.applyProcessorsAndValidators( value, dynamaicPropertiesSchema[key], undefined, false, {}, ) processedInput[key] = itemProcessedInput if (Object.keys(itemErrors).length > 0) { errors[key] = itemErrors } } if (property.type === PropertyType.ARRAY && property.properties) { const arrayOfObjects = arrayZipperProcessor(property, value) const processedArray = [] const processedErrors = [] for (const item of arrayOfObjects) { const { processedInput: itemProcessedInput, errors: itemErrors } = await propsProcessor.applyProcessorsAndValidators( item, property.properties, undefined, false, {}, ) processedArray.push(itemProcessedInput) processedErrors.push(itemErrors) } processedInput[key] = processedArray const isThereErrors = processedErrors.some(error => Object.keys(error).length > 0) if (isThereErrors) { errors[key] = { properties: processedErrors, } } } const processor = processors[property.type] if (processor) { processedInput[key] = await processor(property, processedInput[key]) } const shouldValidate = key !== AUTHENTICATION_PROPERTY_NAME && property.type !== PropertyType.MARKDOWN if (!shouldValidate) { continue } } for (const [key, value] of Object.entries(processedInput)) { const property = props[key] if (isNil(property)) { continue } const validationErrors = validateProperty(property, value, resolvedInput[key]) if (validationErrors.length > 0) { errors[key] = validationErrors } } return { processedInput, errors } }, } const validateProperty = (property: PieceProperty, value: unknown, originalValue: unknown): string[] => { let schema switch (property.type) { case PropertyType.SHORT_TEXT: case PropertyType.LONG_TEXT: schema = z.string({ required_error: `Expected string, received: ${originalValue}`, invalid_type_error: `Expected string, received: ${originalValue}`, }) break case PropertyType.NUMBER: schema = z.number({ required_error: `Expected number, received: ${originalValue}`, invalid_type_error: `Expected number, received: ${originalValue}`, }) break case PropertyType.CHECKBOX: schema = z.boolean({ required_error: `Expected boolean, received: ${originalValue}`, invalid_type_error: `Expected boolean, received: ${originalValue}`, }) break case PropertyType.DATE_TIME: schema = z.string({ required_error: `Invalid datetime format. Expected ISO format (e.g. 2024-03-14T12:00:00.000Z), received: ${originalValue}`, invalid_type_error: `Invalid datetime format. Expected ISO format (e.g. 2024-03-14T12:00:00.000Z), received: ${originalValue}`, }) break case PropertyType.ARRAY: schema = z.array(z.any(), { required_error: `Expected array, received: ${originalValue}`, invalid_type_error: `Expected array, received: ${originalValue}`, }) break case PropertyType.OBJECT: schema = z.record(z.any(), { required_error: `Expected object, received: ${originalValue}`, invalid_type_error: `Expected object, received: ${originalValue}`, }) break case PropertyType.JSON: schema = z.any().refine( (val) => isObject(val) || Array.isArray(val), { message: `Expected JSON, received: ${originalValue}`, }, ) break case PropertyType.FILE: schema = z.record(z.any(), { required_error: `Expected file url or base64 with mimeType, received: ${originalValue}`, invalid_type_error: `Expected file url or base64 with mimeType, received: ${originalValue}`, }) break default: schema = z.any() } let finalSchema if (property.required) { finalSchema = schema } else { finalSchema = schema.nullable().optional() } try { finalSchema.parse(value) return [] } catch (err) { if (err instanceof z.ZodError) { return err.errors.map(e => e.message) } return [] } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server