@sivium/strapi-plugin-polymorphic-relations
v1.0.1
Published
Strapi 5 plugin for polymorphic relations - select any content type and entity in one field with inverse relation support
Maintainers
Readme
Strapi Plugin Polymorphic Relations
A powerful Strapi 5 plugin that adds true polymorphic relations to your content types, allowing you to reference any content type from a single field.
✨ Features
- Polymorphic Relations: Select any content type and entity from a single field
- Inverse Relations: Automatically show reverse relationships (e.g., "which posts reference this category?")
- Standard Populate Support: Works seamlessly with Strapi's
populatequery parameter - Flexible Relation Types: Choose between "Has One" or "Has Many" for both regular and inverse relations
- Auto-Population: Automatically resolves relations in API responses
- TypeScript Support: Full TypeScript definitions included
- Strapi 5 Compatible: Built specifically for Strapi 5 with modern architecture
📦 Installation
npm install strapi-plugin-polymorphic-relations
# or
yarn add strapi-plugin-polymorphic-relations
# or
pnpm add strapi-plugin-polymorphic-relations🚀 Quick Start
1. Enable the Plugin
Add the plugin to your config/plugins.ts:
export default {
'polymorphic-relation': {
enabled: true,
},
};2. Add a Polymorphic Field
- Open Content-Type Builder
- Select a content type
- Click Add another field
- Choose Custom → Polymorphic Relation
- Configure your field options
3. Use in Your Content
The field will appear as two dropdowns:
- Select the content type (e.g., "Article", "Product", "Page")
- Select the specific entry
📖 Field Types
Regular Polymorphic Relation
Allows you to reference any content type from a single field.
Configuration Options:
- Allowed Content Types: Comma-separated UIDs (e.g.,
api::post.post, api::product.product) - Relation Type:
Has One (Single)- Single referenceHas Many (Multiple)- Array of references
- Display Field: Field to show in the selector (default:
title)
API Response (without populate):
{
"myField": {
"contentType": "api::post.post",
"id": "abc123"
}
}API Response (with populate):
{
"myField": {
"__contentType": "api::post.post",
"id": 1,
"documentId": "abc123",
"title": "My Post",
...
}
}Inverse Polymorphic Relation
Shows which entries reference the current entry (read-only, computed field).
Configuration Options:
- Target Model UID: The model to search (e.g.,
api::post.post) - Target Field Name: The polymorphic field name in the target model
- Relation Type:
Has One (Single)- Returns single objectHas Many (Multiple)- Returns array
- Target Display Field: Field to display from target entries
- Label: Custom label for the field
Example Use Case:
If you have a Category content type and Posts that reference categories via a polymorphic field called category, you can add an inverse relation to Category to show all posts that reference it.
API Response (without populate):
{
"relatedPosts": [{ "id": "post1" }, { "id": "post2" }]
}API Response (with populate):
{
"relatedPosts": [
{
"id": 1,
"documentId": "post1",
"title": "First Post",
"category": { ... }
}
]
}🔧 Populate Behavior
The plugin respects Strapi's standard populate query parameter:
Without Populate
GET /api/posts{
"myPolymorphicField": {
"contentType": "api::category.category",
"id": "abc123"
},
"inverseField": [{ "id": "xyz789" }]
}With Wildcard Populate
GET /api/posts?populate=*{
"myPolymorphicField": {
"__contentType": "api::category.category",
"id": 1,
"documentId": "abc123",
"name": "Technology",
...
},
"inverseField": [
{
"id": 1,
"documentId": "xyz789",
"title": "Related Item",
...
}
]
}Specific Field Populate
GET /api/posts?populate[myPolymorphicField]=*Nested Populate
GET /api/posts?populate[myPolymorphicField][populate]=author⚙️ Configuration
Global Configuration
Configure the plugin in config/plugins.ts:
export default {
'polymorphic-relation': {
enabled: true,
config: {
// Whitelist of allowed content types (empty = all allowed)
allowedTypes: ['api::post.post', 'api::product.product', 'api::page.page'],
// Blacklist of ignored content types
ignoredTypes: ['plugin::users-permissions.user', 'admin::user'],
},
},
};Field-Level Configuration
Each field can override global settings:
Regular Polymorphic Relation:
allowedTypes: Comma-separated UIDs to restrict choicesrelationType:oneormanydisplayField: Field to display in selector
Inverse Polymorphic Relation:
targetModel: UID of the model to searchtargetField: Name of the polymorphic field in target modelrelationType:oneormanytargetDisplayField: Field to display from resultslabel: Custom label for the field
🎯 Use Cases
1. Flexible Content References
// A "Hero Section" that can reference any content type
{
"heroContent": {
"contentType": "api::product.product",
"id": "featured-product-123"
}
}2. Related Content
// "You might also like" section with mixed content types
{
"relatedItems": [
{ "contentType": "api::post.post", "id": "post-1" },
{ "contentType": "api::video.video", "id": "video-1" },
{ "contentType": "api::product.product", "id": "product-1" }
]
}3. Reverse Lookups
// Show all content that references this category
{
"usedIn": [
{ "id": 1, "title": "Blog Post", "__contentType": "api::post.post" },
{ "id": 5, "title": "Product", "__contentType": "api::product.product" }
]
}🔌 API Endpoints
The plugin provides REST endpoints for the admin panel:
GET /api/polymorphic-relation/content-types- List available content typesGET /api/polymorphic-relation/content-types/:type/entities- List entities for a typeGET /api/polymorphic-relation/content-types/:type/entities/:id- Get specific entityGET /api/polymorphic-relation/reverse-relations- Find reverse relations
🛠️ Development
Build the Plugin
npm run buildWatch Mode
npm run watchVerify Package
npm run verify📝 TypeScript Support
The plugin includes full TypeScript definitions:
import type {
PolymorphicValue,
ResolvedPolymorphicValue,
} from 'strapi-plugin-polymorphic-relations/server';
// Polymorphic value stored in database
interface PolymorphicValue {
contentType: string;
id: string;
}
// Resolved value with full entity data
interface ResolvedPolymorphicValue {
__contentType: string;
id: number;
documentId: string;
[key: string]: any;
}🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
📄 License
MIT License - see the LICENSE file for details.
🙏 Credits
Developed by Sivium Solutions
📮 Support
🔗 Links
Made with ❤️ for the Strapi community
