Skip to content
This documentation is in construction.

Defining Schemas

Schemas are defined with Epsicube\Schemas\Schema. A schema is a reusable object that describes a data structure and the properties it contains.

Use Schema::create() to instantiate a schema:

use Epsicube\Schemas\Schema;
$schema = Schema::create(
identifier: 'custom::external-api',
title: 'External API configuration',
description: 'Connection settings for the external API integration',
);

The identifier is the stable internal name of the schema. In Epsicube modules, the schema identifier is often the module identifier itself.

Properties are added with ->append([...]):

use Epsicube\Schemas\Enums\StringFormat;
use Epsicube\Schemas\Properties\BooleanProperty;
use Epsicube\Schemas\Properties\IntegerProperty;
use Epsicube\Schemas\Properties\StringProperty;
$schema->append([
'endpoint' => StringProperty::make()
->title('Endpoint')
->format(StringFormat::URL)
->default('https://api.example.test')
->optional(),
'api_key' => StringProperty::make()
->title('API key')
->description('Secret key used to authenticate requests'),
'timeout' => IntegerProperty::make()
->title('Timeout')
->description('Timeout in seconds')
->minimum(1)
->default(10)
->optional(),
'enabled' => BooleanProperty::make()
->title('Enabled')
->default(true)
->optional(),
]);

These two flags solve different problems:

  • optional() controls whether the key may be omitted from the input.
  • nullable() controls whether the value may explicitly be null.

Examples:

  • required and not nullable: the key must be present and must contain a non-null valid value
  • optional and not nullable: the key may be omitted, but if present it must not be null
  • required and nullable: the key must be present, and null is accepted
  • optional and nullable: the key may be omitted, and if present it may be null
use Epsicube\Schemas\Properties\StringProperty;
StringProperty::make()
->title('Display name')
->optional()
->nullable();

Defaults are applied through the property itself and are resolved lazily when needed.

Static default:

use Epsicube\Schemas\Properties\BooleanProperty;
BooleanProperty::make()
->default(true)
->optional();

Dynamic default:

use Epsicube\Schemas\Properties\StringProperty;
StringProperty::make()
->default(fn () => config('app.name'))
->optional();

Defaults are used by:

  • Schema::withDefaults($data)
  • Schema::validated($data)
  • the options system when no persisted value exists
  • Filament exports, where supported
  • prompt exports when no current value is provided

Nested schemas with ObjectProperty and ArrayProperty

Section titled “Nested schemas with ObjectProperty and ArrayProperty”

Nested structures are modeled with ObjectProperty and ArrayProperty.

use Epsicube\Schemas\Properties\ArrayProperty;
use Epsicube\Schemas\Properties\BooleanProperty;
use Epsicube\Schemas\Properties\ObjectProperty;
use Epsicube\Schemas\Properties\StringProperty;
$schema->append([
'credentials' => ObjectProperty::make()
->title('Credentials')
->properties([
'username' => StringProperty::make()->title('Username'),
'password' => StringProperty::make()->title('Password'),
'remember' => BooleanProperty::make()->optional()->default(false),
])
->additionalProperties(false),
'allowed_origins' => ArrayProperty::make()
->title('Allowed origins')
->items(
StringProperty::make()->title('Origin')
)
->uniqueItems()
->optional(),
]);

This is the most common Epsicube pattern: declare module options with a schema inside module(): Module.

use Epsicube\Schemas\Properties\StringProperty;
use Epsicube\Schemas\Schema;
use Epsicube\Support\Modules\Module;
return Module::make('core::json-rpc-server', '1.0.0')
->options(fn (Schema $schema) => $schema->append([
'endpoint' => StringProperty::make()
->title('Endpoint')
->description('Defines the URL path used to expose the JSON-RPC API.')
->optional()
->default('/rpc/v1/endpoint'),
]));

This mirrors the pattern used by built-in modules such as the JSON-RPC server module and the default module stub.

The Schema object also exposes a few helpers that are useful for reuse:

  • ->property(string $name) returns a single property or null
  • ->properties() returns the full property map
  • ->only(string ...$properties) returns a cloned schema limited to selected keys
  • ->except(string ...$properties) returns a cloned schema without selected keys

Example:

$publicSchema = $schema->except('api_key');
$singleFieldSchema = $schema->only('endpoint');

These helpers are especially useful for CLI flows and scoped validation.