Custom Ecosystems
Concept: How to use and extend the Bridge.
What is an Ecosystem?
An ecosystem is a self-contained deployment unit that combines:
- Core Workers — Standard workers from
@mesh/ecosystem - Custom Workers — Your business-specific processors
- Actors — Specialized workers that manage ecosystem operations (reaper, seeder, steward, ambassador)
- Configuration — Bridge configs defining integrations and behaviors
Think of it as a "worker community" — a coordinated group of workers that collectively handle a specific business domain.
Ecosystem Structure
my-ecosystem/
├── ecosystem.ts # Main entry point
├── package.json # Dependencies (includes @mesh/ecosystem)
├── workers/ # Your custom workers
│ └── custom-worker.ts
├── configs/ # Bridge configurations
└── .env # Environment variables
How Ecosystems Work
- Import Core — Ecosystem imports the core framework (
@mesh/ecosystem) - Define Workers — Register core and custom workers in a library
- Configure Actors — Set up management actors (reaper, seeder, etc.)
- Spawn Embryo — Initialize the ecosystem with worker and actor libraries
Ecosystem Philosophy
CommerceBridge provides a base framework with core commerce operations. You extend it by creating ecosystems that add:
- External system integrations
- Custom business logic
- Tenant-specific workflows
- Industry-specific features
Rule: Extend, don't modify. Keep the core generic.
Building an Ecosystem
1. Install Core Package
{
"name": "my-ecosystem",
"dependencies": {
"@mesh/ecosystem": "~0.0.6-build1",
"dotenv": "^16.0.3",
"pm2": "^5.3.0"
}
}
2. Create Ecosystem Entry Point
import * as mesh from "@mesh/ecosystem/ecosystem";
import { myCustomWorker } from './workers/my-custom-worker';
// Initialize ecosystem
const ecosystem = new mesh.core_models.ecosystemModel.Ecosystem();
// Register actors (ecosystem management)
const actorLibrary = {
"reaper": mesh.core_community.actor_reaper.actor_reaper,
"seeder": mesh.core_community.actor_seeder.actor_seeder,
"steward": mesh.core_community.actor_steward.actor_steward,
"ambassador": mesh.core_community.actor_ambassador.actor_ambassador
};
// Register workers (core + custom)
const workerLibrary = {
// Core workers from framework
"commerce/engagementRecalculator": mesh.core_workers.worker_commerce_engagement_reCaculator,
"search/indexFromDatastore": mesh.core_workers.worker_search_openSearch_indexFromDatastore,
// Your custom workers
"custom/myBusinessProcess": myCustomWorker
};
// Spawn the ecosystem
new mesh.core_models.workerEmbyroModel.WorkerEmbryo(
workerLibrary,
actorLibrary,
process.env.COMMUNITY_ID || "",
ecosystem
);
3. Configure Environment
# .env
COMMUNITY_ID=my-commerce-community
BRIDGE_CONFIG_ID=commerce-bridge-prod
4. Run the Ecosystem
# Development (single worker)
npm run start-dev -- --actor=myWorkerName
# Production (full community with PM2)
npm start
Extension Patterns
Pattern 1: External System Integration
export class EcosystemBridge extends BaseBridge {
private externalClient: ExternalSystemClient
constructor(config: BridgeConfig) {
super(config)
this.externalClient = new ExternalSystemClient(config.external)
}
async syncToExternalSystem(engagement: Engagement) {
const externalFormat = this.transform(engagement)
return await this.externalClient.sync(externalFormat)
}
}
Pattern 2: Custom Validation
export class ValidatedBridge extends BaseBridge {
async createEngagement(params: EngagementParams) {
// Add custom validation
await this.validateCustomRules(params)
// Call base implementation
const engagement = await super.createEngagement(params)
// Post-creation hooks
await this.notifyStakeholders(engagement)
return engagement
}
}
Pattern 3: Workflow Customization
export class WorkflowBridge extends BaseBridge {
async updateEngagement(id: string, updates: Partial<Engagement>) {
const current = await this.getEngagement(id)
// Custom workflow logic
if (this.requiresApproval(current, updates)) {
await this.triggerApprovalWorkflow(id, updates)
return current // Don't update yet
}
return await super.updateEngagement(id, updates)
}
private requiresApproval(current: Engagement, updates: Partial<Engagement>) {
// Your approval logic
return updates.status === 'confirmed' &&
current.pricing.finalPrice > 10000
}
}
Best Practices
✅ Do
- Use inheritance — Extend BaseBridge, don't fork it
- Keep extensions focused — One concern per extension
- Document your additions — Help future maintainers
- Use dependency injection — Pass clients via config
- Maintain multi-tenant safety — Always include tenant context
- Test extensions independently — Unit test your additions
❌ Don't
- Modify base classes — Always extend
- Bypass core functions — Use inherited methods
- Hardcode configuration — Use config injection
- Mix concerns — Keep integrations separate
- Ignore tenant context — Always scope operations
- Create deep inheritance chains — Keep it simple
Configuration Pattern
Bridge configuration follows a structured model that separates concerns and integrations:
interface BridgeConfig {
_id: string
theme: string // Organizational grouping
topic: string // Functional area
concern: string // Specific concern within topic
config: {
modules: {
[key: string]: {
integration: string // Which integration service to use
}
}
integrations: {
[key: string]: {
integration: string // Integration service class name
uri?: string // Connection URI
poolSize?: number // Connection pool size
timeoutMs?: number // Operation timeout
}
}
}
}
Example Configuration:
const bridgeConfig: BridgeConfig = {
_id: 'commerce-bridge-prod',
theme: 'commerce',
topic: 'order-processing',
concern: 'fulfillment',
config: {
modules: {
messaging: {
integration: 'kafka'
},
database: {
integration: 'mongodb'
},
search: {
integration: 'opensearch'
}
},
integrations: {
kafka: {
integration: 'KafkaIntegrationService',
uri: 'kafka://localhost:9092',
timeoutMs: 5000
},
mongodb: {
integration: 'MongoDBIntegrationService',
uri: 'mongodb://localhost:27017',
poolSize: 10
},
opensearch: {
integration: 'OpenSearchIntegrationService',
uri: 'https://localhost:9200'
}
}
}
}
Available Integration Types:
- Messaging: Kafka, RabbitMQ
- Data: MongoDB
- Search: OpenSearch
- Communication: Twilio, Mailgun
- Utility: Crypto, OpenAI, Strapi
Testing Extensions
Unit Testing
describe('CustomBridge', () => {
let bridge: CustomBridge
beforeEach(() => {
bridge = new CustomBridge(testConfig)
})
it('should sync to ERP', async () => {
const engagement = createTestEngagement()
const result = await bridge.syncToErp(engagement)
expect(result.success).toBe(true)
})
})
Integration Testing
describe('Custom Workflow', () => {
it('should trigger approval for large orders', async () => {
const engagement = await bridge.createEngagement(largeOrderParams)
await bridge.updateEngagement(engagement.id, {
status: 'confirmed'
})
// Verify approval workflow triggered
const approvals = await bridge.getPendingApprovals()
expect(approvals).toContain(engagement.id)
})
})
Deployment
Package Your Extensions
my-ecosystem/
├── bridge/
│ └── custom-bridge.ts
├── workers/
│ ├── order-processor.ts
│ └── inventory-sync.ts
└── config/
└── bridge-config.ts
Custom Ecosystems: Your workers, your community, our foundation.