timeax / ui-config-schema
SDK config schema designed to provide a general shape for Input field configurations
v0.0.2
2026-01-27 04:30 UTC
README
# Timeax UI Config Schema Portable, framework-agnostic primitives for describing **UI configuration forms** (fields, options, rules, secrets) and returning **structured validation results**. This package is meant to be shared across SDKs and host apps so they can expose a consistent “config UI schema” without coupling to any specific UI framework (React/Vue/etc.) or product domain (payments, plugins, etc.). It supports both: - **Flat schemas** (classic `ConfigSchema` → `ConfigField[]`) - **Forti-style nested schemas** (tree: `UiConfigSchema` → `settings: { key: ConfigNode }` with `ConfigGroup` + `ConfigField`) --- ## Installation ```bash composer require timeax/ui-config-schema
What this package provides
Forti-style tree schema
UiConfigSchema: root container withsettings: array<string, ConfigNode>ConfigTab: optional UI tab metadata (id,label,parentId,includes,excludes)ConfigNode: node interface (either a group or a field)ConfigGroup: a group node containingchildren: array<string, ConfigNode>ConfigField: a field node (leaf) — also implementsConfigNode
Flat schema (backwards-compatible)
ConfigSchema: a list ofConfigFieldobjects
Options
ConfigOption: discrete option values for selects/radios/multiselect, etc.
Config values container
ConfigBag: holdsoptions+secrets, supports looking up values and filtering by schema (secrets excluded from default serialization)
Validation results
ConfigValidationResult: consistent shape for validation outcomes + field errorsConfigValidationError: a single field-level error record
Optional contract
ProvidesConfigSchema: a tiny interface for anything that can expose a schema
Included JSON Schema
This repository ships a Draft-07 JSON Schema that mirrors the Forti-style structure:
schema/timeax.ui-config-schema.draft-07.json
It validates objects shaped like:
{
"settings": {
"gateway": {
"type": "group",
"label": "Gateway",
"children": {
"public_key": {
"label": "Public Key",
"type": "text",
"required": true
},
"secret_key": {
"label": "Secret Key",
"type": "password",
"required": true,
"secret": true
}
}
}
}
}
Quick examples
1) Define a Forti-style tree schema
<?php use Timeax\ConfigSchema\Schema\ConfigField; use Timeax\ConfigSchema\Schema\ConfigGroup; use Timeax\ConfigSchema\Schema\UiConfigSchema; use Timeax\ConfigSchema\Schema\ConfigOption; use Timeax\ConfigSchema\Schema\ConfigTab; $schema = new UiConfigSchema( settings: [ 'gateway' => new ConfigGroup( label: 'Gateway', tabs: ['payments'], children: [ 'public_key' => new ConfigField( name: 'public_key', label: 'Public Key', required: true, tabs: ['payments'], ), 'secret_key' => new ConfigField( name: 'secret_key', label: 'Secret Key', type: 'password', required: true, secret: true, tabs: ['payments'], ), ], ), 'mode' => new ConfigField( name: 'mode', label: 'Mode', type: 'select', required: true, isButton: true, includes: ['gateway'], options: [ new ConfigOption('card', 'Card', id: 'mode_card', includes: ['public_key']), new ConfigOption('bank', 'Bank Transfer', id: 'mode_bank', includes: ['secret_key']), ], ), ], tabs: [ new ConfigTab(id: 'payments', label: 'Payments'), new ConfigTab(id: 'advanced', label: 'Advanced', parentId: 'payments'), ], );
2) Flatten a tree schema into a flat schema
flatten() traverses the tree and returns a ConfigSchema(fields[]).
It also stamps each field with its group path so the structure can be rebuilt later.
<?php $flat = $schema->flatten(); // ConfigSchema { fields: ConfigField[] } // Each field may carry ->group (e.g. "gateway")
3) Rebuild a Forti-style tree from a flat schema
<?php use Timeax\ConfigSchema\Schema\ConfigSchema; /** @var ConfigSchema $flat */ $tree = $flat->toUiConfigSchema();
4) Store config values with options + secrets
<?php use Timeax\ConfigSchema\Support\ConfigBag; $config = new ConfigBag( sandbox: true, options: [ 'mode' => 'card', 'public_key' => 'pk_test_...', ], secrets: [ 'secret_key' => 'sk_test_...', ], ); // secrets are excluded from jsonSerialize by default $public = $config->jsonSerialize();
5) Validation result example
<?php use Timeax\ConfigSchema\Support\ConfigValidationResult; $result = ConfigValidationResult::fail() ->addError('public_key', 'Required') ->addError('secret_key', 'Required'); if (! $result->isOk()) { return $result->jsonSerialize(); }
Notes on secrets
ConfigBag::jsonSerialize()intentionally excludes secrets.- Use
ConfigField::$secret = trueto mark a field as sensitive. - Hosts should still enforce secret-handling (mask in UI, avoid logs, encrypt at rest if desired).
License
MIT