socialdept/atp-schema
最新稳定版本:v0.3.2
Composer 安装命令:
composer require socialdept/atp-schema
包简介
ATProto Lexicon parser and validator with DTO generation for Laravel
README 文档
README
Parse, validate, and transform AT Protocol Lexicon schemas in Laravel.
What is Schema?
Schema is a Laravel package for working with AT Protocol Lexicon schemas. It provides comprehensive tools for parsing schema definitions, validating data against those schemas, handling file uploads (blobs), and transforming between raw data and domain models.
Think of it as your complete toolkit for building AT Protocol applications that need strict data validation and schema compliance.
Why use Schema?
- Complete Lexicon support - All types, formats, and constraints from the AT Protocol spec
- Multiple validation modes - STRICT, OPTIMISTIC, and LENIENT for different use cases
- Laravel integration - Works seamlessly with Laravel's validation and storage systems
- Blob handling - Built-in file upload validation and storage
- Model transformation - Convert between arrays and domain objects
- Union types - Full support for discriminated unions with
$typefields - Extensible - Macros and hooks let you customize behavior
- Production ready - 818 passing tests with comprehensive coverage
- Pre-generated classes - Includes type-safe PHP classes for all standard AT Protocol & Bluesky lexicons
Pre-Generated Lexicon Classes
Schema ships with pre-generated PHP classes for all standard AT Protocol and Bluesky lexicons, providing immediate type-safe access without any generation step:
use SocialDept\AtpSchema\Generated\App\Bsky\Feed\Post; use SocialDept\AtpSchema\Generated\App\Bsky\Graph\Follow; use SocialDept\AtpSchema\Generated\Com\Atproto\Repo\StrongRef; // Create type-safe records $post = new Post( text: 'Hello ATP!', createdAt: now() ); // Create references $ref = new StrongRef( uri: 'at://did:plc:example/app.bsky.feed.post/123', cid: 'bafyreic3...' ); // Validate and use Schema::validate('app.bsky.feed.post', $post); // true
Available Pre-Generated Classes
Schema includes 220+ pre-generated classes covering all standard AT Protocol and Bluesky lexicons:
Record Types (SocialDept\AtpSchema\Generated\App\Bsky\*)
Feed\Post- Social media postsFeed\Like- Like recordsFeed\Repost- Repost recordsGraph\Follow- Follow relationshipsGraph\Block- Block recordsGraph\List- User listsGraph\Listitem- List itemsLabeler\Service- Labeler service records
Embed Types
Embed\Images- Image embedsEmbed\External- External link embedsEmbed\Record- Record embedsEmbed\RecordWithMedia- Record with media embedsEmbed\Video- Video embeds
Feed & Post Views (App\Bsky\Feed\Defs\*)
PostView- Post with engagement metricsFeedViewPost- Post in feed contextThreadViewPost- Post in thread contextReplyRef- Reply referencesViewerState- User's interaction state
Actor & Profile Views (App\Bsky\Actor\Defs\*)
ProfileView- Full profile viewProfileViewBasic- Basic profile viewProfileViewDetailed- Detailed profile viewViewerState- Viewer's relationship to profile- Plus 25+ preference and state classes
Graph & Social Views (App\Bsky\Graph\Defs\*)
ListView- List viewsListItemView- List item viewsRelationship- User relationshipsStarterPackView- Starter pack views
Rich Text (App\Bsky\Richtext\Facet\*)
Facet- Text annotations (mentions, URLs, hashtags)Mention- User mention facetsLink- URL link facetsTag- Hashtag facets
AT Protocol Core (Com\Atproto\*)
Repo\StrongRef- Content-addressed record referencesRepo\Defs\CommitMeta- Repository commit metadataLabel\Defs\Label- Content labelsAdmin\Defs\*- Administrative tools (20+ classes)Sync\SubscribeRepos\*- Repository sync events (6+ classes)Server\Defs\*- Server definitions
Moderation (Tools\Ozone\*)
Moderation\Defs\*- Moderation definitionsCommunication\Defs\*- Moderation communication
Generated Enums
Schema also generates PHP 8.1+ enums for string types with known values:
Moderation
Com\Atproto\Moderation\ReasonType- Report reason types (spam, violation, etc.)Com\Atproto\Moderation\SubjectType- Report subject types (account, record, chat)
Labels & Content
Com\Atproto\Label\LabelValue- Content label values
Graph & Social
App\Bsky\Graph\ListPurpose- List purpose types (modlist, curatelist)App\Bsky\Actor\MutedWordTarget- Muted word target types
Moderation Tools
Tools\Ozone\Moderation\SubjectReviewState- Review state values
Publishing Source Lexicons
Developers can optionally publish the source JSON lexicons to their project for reference or custom generation:
php artisan vendor:publish --tag=atp-lexicons
This copies all lexicon JSON files to resources/lexicons/.
Quick Example
use SocialDept\AtpSchema\Data\LexiconDocument; use SocialDept\AtpSchema\Validation\Validator; use SocialDept\AtpSchema\Parser\SchemaLoader; // Load a schema $schema = LexiconDocument::fromArray([ 'lexicon' => 1, 'id' => 'app.bsky.feed.post', 'defs' => [ 'main' => [ 'type' => 'record', 'record' => [ 'type' => 'object', 'required' => ['text', 'createdAt'], 'properties' => [ 'text' => ['type' => 'string', 'maxLength' => 300], 'createdAt' => ['type' => 'string', 'format' => 'datetime'], ], ], ], ], ]); // Validate data $validator = new Validator(new SchemaLoader([])); $data = [ 'text' => 'Hello, AT Protocol!', 'createdAt' => '2024-01-01T12:00:00Z', ]; if ($validator->validate($data, $schema)) { // Data is valid! } // Get Laravel-formatted errors $errors = $validator->validateWithErrors($invalidData, $schema); // ['text' => ['The text field exceeds maximum length.']]
Installation
composer require socialdept/atp-schema
The package will auto-register with Laravel. Optionally publish the config:
php artisan vendor:publish --tag=schema-config
Basic Usage
Validation Modes
Choose the validation strictness that fits your use case:
use SocialDept\AtpSchema\Validation\Validator; // STRICT - Rejects unknown fields $validator->setMode(Validator::MODE_STRICT); // OPTIMISTIC - Allows unknown fields (default) $validator->setMode(Validator::MODE_OPTIMISTIC); // LENIENT - Skips constraint validation $validator->setMode(Validator::MODE_LENIENT);
Handling Blobs
Upload and validate files with built-in constraints:
use SocialDept\AtpSchema\Services\BlobHandler; $blobHandler = new BlobHandler('local'); $blob = $blobHandler->store(request()->file('image'), [ 'accept' => ['image/*'], 'maxSize' => 1024 * 1024 * 5, // 5MB ]); // Use in validated data $data = [ 'image' => $blob->toArray(), ];
Model Transformation
Transform between raw arrays and domain objects:
use SocialDept\AtpSchema\Services\ModelMapper; use SocialDept\AtpSchema\Contracts\Transformer; class Post { public function __construct( public string $text, public string $createdAt ) {} } class PostTransformer implements Transformer { public function fromArray(array $data): Post { return new Post( text: $data['text'], createdAt: $data['createdAt'] ); } public function toArray(mixed $model): array { return [ 'text' => $model->text, 'createdAt' => $model->createdAt, ]; } public function supports(string $type): bool { return $type === 'app.bsky.feed.post'; } } // Register and use $mapper = new ModelMapper(); $mapper->register('app.bsky.feed.post', new PostTransformer()); $post = $mapper->fromArray('app.bsky.feed.post', $data); $array = $mapper->toArray('app.bsky.feed.post', $post);
Union Types
Work with discriminated unions using the $type field:
use SocialDept\AtpSchema\Services\UnionResolver; $resolver = new UnionResolver(); $data = [ '$type' => 'app.bsky.embed.images', 'images' => [/* ... */], ]; $type = $resolver->extractType($data); // "app.bsky.embed.images" // Validate discriminated union $refs = ['app.bsky.embed.images', 'app.bsky.embed.video']; $resolver->validateDiscriminated($data, $refs);
Complete Workflow Example
Here's how to validate a post with an image upload:
use SocialDept\AtpSchema\Data\LexiconDocument; use SocialDept\AtpSchema\Validation\Validator; use SocialDept\AtpSchema\Services\BlobHandler; // Load schema $schema = LexiconDocument::fromArray([/* ... */]); // Handle image upload $blobHandler = new BlobHandler('local'); $blob = $blobHandler->store(request()->file('image'), [ 'accept' => ['image/*'], 'maxSize' => 1024 * 1024 * 5, ]); // Create post data $postData = [ 'text' => 'Check out this photo!', 'createdAt' => now()->toIso8601String(), 'embed' => [ '$type' => 'app.bsky.embed.images', 'images' => [ [ 'image' => $blob->toArray(), 'alt' => 'A beautiful sunset', ], ], ], ]; // Validate $validator = new Validator(new SchemaLoader([])); if ($validator->validate($postData, $schema)) { // Store post... } else { $errors = $validator->validateWithErrors($postData, $schema); // Handle errors... }
Supported Types
Schema supports all AT Protocol Lexicon types:
- Primitives -
string,integer,boolean,bytes - Objects - Nested objects with properties
- Arrays - Sequential lists with item validation
- Blobs - File uploads with mime type and size constraints
- Unions - Discriminated unions with
$typefield - Unknown - Accept any value
Supported Formats
Built-in validators for AT Protocol formats:
datetime- ISO 8601 timestampsuri- Valid URIsat-uri- AT Protocol URIsdid- Decentralized identifiersnsid- Namespaced identifierscid- Content identifiers
Advanced Features
Extension Hooks
Add custom logic at key points in the validation lifecycle:
use SocialDept\AtpSchema\Support\ExtensionManager; $extensions = new ExtensionManager(); $extensions->hook('before:validate', function ($data) { $data['text'] = trim($data['text']); return $data; }); $transformed = $extensions->filter('before:validate', $data);
Macros
Extend core services with custom methods:
use SocialDept\AtpSchema\Services\ModelMapper; ModelMapper::macro('validateAndTransform', function ($type, $data, $schema) { if (!$this->validator->validate($data, $schema)) { return null; } return $this->fromArray($type, $data); }); $mapper = new ModelMapper(); $result = $mapper->validateAndTransform('app.bsky.feed.post', $data, $schema);
API Reference
Core Classes
LexiconDocument
LexiconDocument::fromArray(array $data): self LexiconDocument::fromJson(string $json): self $document->getNsid(): string $document->getVersion(): int $document->getDefinition(string $name): ?array $document->getMainDefinition(): ?array
Validator
$validator->validate(array $data, LexiconDocument $schema): bool $validator->validateWithErrors(array $data, LexiconDocument $schema): array $validator->setMode(string $mode): self
BlobHandler
$handler->store(UploadedFile $file, array $constraints = []): BlobReference $handler->storeFromString(string $content, string $mimeType): BlobReference $handler->get(string $ref): ?string $handler->delete(string $ref): bool $handler->exists(string $ref): bool
ModelMapper
$mapper->register(string $type, Transformer $transformer): self $mapper->fromArray(string $type, array $data): mixed $mapper->toArray(string $type, mixed $model): array $mapper->fromArrayMany(string $type, array $items): array
UnionResolver
$resolver->extractType(array $data): ?string $resolver->validateDiscriminated(mixed $data, array $refs): void $resolver->getTypeDefinition(array $data, array $definition): ?LexiconDocument
Testing
Run the test suite:
vendor/bin/phpunit
Run specific test categories:
# Unit tests only vendor/bin/phpunit --testsuite=unit # Integration tests only vendor/bin/phpunit --testsuite=integration
Configuration
Customize behavior in config/schema.php:
return [ 'storage' => [ 'disk' => env('SCHEMA_STORAGE_DISK', 'local'), ], 'validation' => [ 'mode' => env('SCHEMA_VALIDATION_MODE', 'optimistic'), ], 'blob' => [ 'max_size' => env('SCHEMA_BLOB_MAX_SIZE', 1024 * 1024 * 10), // 10MB ], ];
Requirements
- PHP 8.2+
- Laravel 11+
Resources
Support & Contributing
Found a bug or have a feature request? Open an issue.
Want to contribute? We'd love your help! Check out the contribution guidelines.
Credits
- Miguel Batres - founder & lead maintainer
- All contributors
License
Schema is open-source software licensed under the MIT license.
Built for the Federation • By Social Dept.
统计信息
- 总下载量: 13
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 1
- 依赖项目数: 2
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-11-23
