@rashidazarang/propertyware-adapter
v1.0.0
Published
PropertyWare SOAP API adapter for property management integrations
Maintainers
Readme
PropertyWare Adapter
A TypeScript/JavaScript adapter for integrating with PropertyWare's SOAP API. This adapter provides a clean, promise-based interface for property management operations.
🚀 Features
- Full CRUD Operations for portfolios, buildings, work orders, leases, and tenants
- Built-in Rate Limiting (2 requests/second as per PropertyWare limits)
- Automatic Retry Logic with exponential backoff
- Batch Operations Support for efficient data processing
- TypeScript Support with full type definitions
- Comprehensive Error Handling with detailed error messages
- Connection Pooling for optimal performance
📦 Installation
npm install @pmip/propertyware-adapteror
yarn add @pmip/propertyware-adapter🔧 Configuration
import { PropertyWareAdapter } from '@pmip/propertyware-adapter';
const adapter = new PropertyWareAdapter({
username: 'your-username',
password: 'your-password',
url: 'https://api.propertyware.com',
wsdl: 'https://api.propertyware.com/services?wsdl',
options: {
rateLimit: 2, // requests per second (default: 2)
retryAttempts: 3, // number of retry attempts (default: 3)
timeout: 30000, // request timeout in ms (default: 30000)
batchSize: 100 // batch operation size (default: 100)
}
});
// Initialize the connection
await adapter.connect();📖 Usage Examples
Basic Operations
Get All Portfolios
const portfolios = await adapter.getPortfolios();
console.log(`Found ${portfolios.length} portfolios`);Get Portfolio by ID
const portfolio = await adapter.getPortfolio('4550688770');
console.log(portfolio.name);Create Work Order
const workOrder = await adapter.createWorkOrder({
portfolioId: '4550688770',
buildingId: '5031395333',
unitId: '6789',
type: 'Maintenance',
priority: 'High',
description: 'Fix leaking faucet',
tenantId: '12345'
});
console.log(`Created work order: ${workOrder.id}`);Batch Operations
// Batch fetch with automatic pagination
const allWorkOrders = await adapter.getWorkOrders({
portfolioIds: ['4550688770', '4550688772'],
status: 'Open',
batchSize: 50
});
// Batch update
const updates = workOrders.map(wo => ({
id: wo.id,
status: 'In Progress'
}));
await adapter.batchUpdateWorkOrders(updates);Advanced Filtering
// Get work orders with filters
const workOrders = await adapter.getWorkOrders({
portfolioId: '4550688770',
status: 'Open',
priority: 'High',
dateFrom: new Date('2025-01-01'),
dateTo: new Date('2025-12-31')
});
// Get leases expiring soon
const expiringLeases = await adapter.getLeases({
expiresWithin: 90, // days
portfolioId: '4550688770'
});Error Handling
try {
const portfolio = await adapter.getPortfolio('invalid-id');
} catch (error) {
if (error.code === 'PORTFOLIO_NOT_FOUND') {
console.error('Portfolio not found');
} else if (error.code === 'RATE_LIMIT_EXCEEDED') {
console.error('Rate limit exceeded, please retry later');
} else {
console.error('Unexpected error:', error.message);
}
}🏗️ API Reference
Portfolio Operations
getPortfolios(options?: PaginationOptions): Promise<Portfolio[]>getPortfolio(id: string): Promise<Portfolio>createPortfolio(data: PortfolioInput): Promise<Portfolio>updatePortfolio(id: string, data: Partial<PortfolioInput>): Promise<Portfolio>deletePortfolio(id: string): Promise<void>
Building Operations
getBuildings(portfolioId?: string): Promise<Building[]>getBuilding(id: string): Promise<Building>createBuilding(data: BuildingInput): Promise<Building>updateBuilding(id: string, data: Partial<BuildingInput>): Promise<Building>deleteBuilding(id: string): Promise<void>
Work Order Operations
getWorkOrders(filters?: WorkOrderFilters): Promise<WorkOrder[]>getWorkOrder(id: string): Promise<WorkOrder>createWorkOrder(data: WorkOrderInput): Promise<WorkOrder>updateWorkOrder(id: string, data: Partial<WorkOrderInput>): Promise<WorkOrder>batchUpdateWorkOrders(updates: WorkOrderUpdate[]): Promise<void>
Lease Operations
getLeases(filters?: LeaseFilters): Promise<Lease[]>getLease(id: string): Promise<Lease>createLease(data: LeaseInput): Promise<Lease>updateLease(id: string, data: Partial<LeaseInput>): Promise<Lease>
Tenant Operations
getTenants(options?: PaginationOptions): Promise<Tenant[]>getTenant(id: string): Promise<Tenant>createTenant(data: TenantInput): Promise<Tenant>updateTenant(id: string, data: Partial<TenantInput>): Promise<Tenant>
🔒 Rate Limiting
PropertyWare enforces a rate limit of 2 requests per second. This adapter automatically handles rate limiting with:
- Built-in request queuing
- Automatic throttling
- Configurable rate limits
- Retry logic with exponential backoff
// Configure custom rate limiting
const adapter = new PropertyWareAdapter({
// ... credentials
options: {
rateLimit: 1, // More conservative: 1 request per second
retryAttempts: 5,
retryDelay: 2000 // Initial retry delay in ms
}
});🧪 Testing
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run with coverage
npm run test:coverage🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
🆘 Support
- Documentation: Full API Documentation
- Issues: GitHub Issues
- Discussions: GitHub Discussions
🔗 Related Projects
- PMIP Core - The main integration platform
- ServiceFusion Adapter - ServiceFusion REST API adapter
📈 Roadmap
- [ ] Support for custom fields
- [ ] Webhook support
- [ ] File upload/download operations
- [ ] Report generation
- [ ] Bulk import/export
- [ ] GraphQL wrapper (optional)
⚠️ Disclaimer
This adapter is not officially affiliated with or endorsed by PropertyWare. PropertyWare is a registered trademark of RealPage, Inc.
