Blueprint & build
Blueprint middleware
The Blueprint is not assembled by one function; it is produced by a pipeline that runs once, before the first event. Each step receives the manifest so far and refines it. Extending setup means inserting a step, never editing the core.
#Setup is a pipeline
The principle
Configuration built by one closed function can only change by editing that function. Configuration built by a pipeline changes by insertion. Composition replaces modification, which is what keeps a small core open to a large ecosystem.
In Stone.js
The BlueprintBuilder runs a chain of blueprint middleware. Each is a pipe: it gets the build context (the manifest under construction), does its work, and calls next. Adapters and extensions contribute steps; so can you.
import { defineBlueprintMiddleware } from '@stone-js/core'
export const withTaskDefaults = defineBlueprintMiddleware((context, next) => {
const { blueprint } = context
if (!blueprint.has('stone.tasks.pageSize')) {
blueprint.set('stone.tasks.pageSize', 20) // refine the manifest
}
return next(context) // hand it to the next step
})The manifest is not configured, it is composed, one step at a time, before the first event.
#Reading what earlier steps decided
Because steps run in order, a later step can inspect what earlier ones wrote and react. That is how an extension can, say, register a default only when an adapter is present, without the two knowing about each other.
export const withEdgeTuning = defineBlueprintMiddleware((context, next) => {
const { blueprint } = context
if (blueprint.has('stone.adapters.fetch')) {
blueprint.set('stone.cache.driver', 'edge') // adapt to what is already there
}
return next(context)
})