Skip to content

Props Transformation

System that intercepts and modifies props before rendering — the "intelligent filter" between schema and component.

Middleware

Middleware Pipeline allows modifying component behavior without changing code:

What It Does:

InputMiddlewareTransformationOutput
Raw props from schemaTemplate expression middlewareReplaces {{ $formValues.x }}, {{ $externalContext.x }}Resolved props
Props + schema + contextCustom middlewareValidation, formatting, logicFinal props
Component propsYour middlewareAny transformationEnhanced props

Pipeline Flow:

Sequential Execution (array order):

text
Raw Props → Middleware 1 → Middleware 2 → ... → Final Props → Component

Built-in: The template expression middleware runs first (when using FormFactory), so form values and external context are available for substitution. Then any middlewares you pass (Provider middlewares and factory middlewares) run in order.

Result: Basic props → Enriched props. Functionality without duplicated code!

Middleware Interface

Signature (from @schepta/core):

typescript
import type { MiddlewareFn, MiddlewareContext } from '@schepta/core';

const myMiddleware: MiddlewareFn = (props, schema, context) => {
  // props: current props object
  // schema: the schema node for this component
  // context: MiddlewareContext
  return { ...props, /* your changes */ };
};

MiddlewareContext provides:

  • formValues — current form values (for form-aware middleware)
  • externalContext — Provider externalContext (user, API, etc.)
  • debug — debug utilities when debug is enabled
  • formAdapter — form adapter when available (e.g. in FormFactory)

Registration: Middlewares are passed as an array, not an object. Order of execution is the order in the array.

typescript
<ScheptaProvider middlewares={[templateMiddleware, withValidation, withAnalytics]}>
  ...
</ScheptaProvider>

// Or per factory
<FormFactory schema={schema} middlewares={[customMiddleware]} />

The pipeline applies middlewares in sequence; each receives the result of the previous. Use applyMiddlewares from core if you need to run the same pipeline elsewhere.

Middleware Patterns

Transformation patterns:

PatternPurposeImplementation
EnhancerAdd functionality(props, schema, context) => ({ ...props, newFeature })
FilterRemove/modify props(props) => omit(props, 'sensitiveData')
MapperTransform values(props) => ({ ...props, value: transform(props.value) })
ConditionalApply conditionally(props, schema, context) => condition ? enhance(props) : props

Example – logging wrapper:

typescript
const withLogging = (next: MiddlewareFn): MiddlewareFn => (props, schema, context) => {
  if (context.debug?.isEnabled) {
    context.debug.log('middleware', 'Before', props);
  }
  const result = next(props, schema, context);
  if (context.debug?.isEnabled) {
    context.debug.log('middleware', 'After', result);
  }
  return result;
};

Middleware Pipeline is the "props processor" used by other concepts: