@ticatec/app-data-manager
v2.0.0
Published
A comprehensive TypeScript library providing hierarchical data manager classes for CRUD operations, pagination, and data management in frontend applications. Features include full list, paged, and stackable data managers with built-in caching and transfor
Readme
App Data Manager
Current version: 2.0.0 | A comprehensive TypeScript library that provides a hierarchical set of data manager classes for handling CRUD operations and paginated data retrieval via HTTP requests. This library simplifies data management in frontend applications by abstracting the complexity of data operations and providing a structured approach to managing different types of datasets.
Note: This is a pure ESM (ES Module) package. Only
importsyntax is supported.
Features
- Type-safe: Full TypeScript support with comprehensive type definitions
- Hierarchical Architecture: Well-structured inheritance hierarchy for different data management needs
- Pagination Support: Built-in pagination handling with both standard and stackable pagination
- CRUD Operations: Complete Create, Read, Update, Delete functionality
- Data Transformation: Built-in data conversion and validation support
- Extensible: Easy to extend and customize for specific use cases
- Dependency Injection: Service-based architecture for better testability
Installation
npm install @ticatec/app-data-managerQuick Start
import { PagedDataManager } from '@ticatec/app-data-manager';
import { PagingDataService } from '@ticatec/app-data-service';
// 1. Create a data service
class UserService extends PagingDataService {
constructor() {
super('/api/users');
}
}
// 2. Create a data manager
const userManager = new PagedDataManager(new UserService(), 'id', {
tagData: { status: 'active' } // Default filter criteria
});
// 3. Load data
await userManager.search({ role: 'admin' });
console.log(`Found ${userManager.count} users`);
console.log(`Page ${userManager.pageNo} of ${userManager.pageCount}`);
console.log(userManager.list); // Current page users🤖 AI-Assisted Development
Accelerate your development with AI-powered code generation!
This library includes comprehensive AI coding assistant prompts optimized for Claude Code and other AI assistants. These prompts help you generate correct, consistent code faster.
📁 Available Prompts
prompts/AI_CODING_ASSISTANT_EN.md- Complete guide in Englishprompts/AI_CODING_ASSISTANT_CN.md- 完整指南(中文)prompts/CLAUDE_CODE_GUIDE.md- Quick start guideprompts/QUICK_REFERENCE.md- Decision trees and cheat sheets
🚀 Quick Start with AI
For Claude Code users:
# In your Claude Code conversation, simply reference the prompt:
Follow prompts/AI_CODING_ASSISTANT_EN.md
Create a user management feature with pagination, search, and CRUD operationsClaude Code will automatically:
- ✅ Analyze your existing codebase patterns
- ✅ Generate services and managers following best practices
- ✅ Match your coding style and conventions
- ✅ Place files in correct locations
- ✅ Handle imports and exports
💡 Example Usage
# 1. Create a new feature
Follow prompts/AI_CODING_ASSISTANT_EN.md
Create product management with infinite scroll
# 2. Refactor existing code
Review all managers and apply best practices from the prompt
# 3. Add features
Add bulk delete to OrderManager following existing patterns
# 4. Understand patterns
Explain when to use PagedDataManager vs StackDataManager🎯 Benefits
- Faster Development: Generate complete features in seconds
- Consistency: Maintain patterns across your codebase
- Best Practices: Built-in knowledge of anti-patterns and optimization tips
- Context-Aware: AI reads your existing code and matches your style
- Error Prevention: Common mistakes are highlighted and avoided
📚 What's Included
The AI prompts cover:
- 🏗️ Architecture overview - Two-layer design (Service + Manager)
- 📋 Decision trees - Choose the right class for your needs
- 🏃 Code patterns - 6 common patterns with examples
- ✅ Best practices - Performance, error handling, type safety
- ⚠️ Common mistakes - Anti-patterns and how to avoid them
- 🎓 Advanced patterns - Custom endpoints, data transformation
- 🔍 Quick reference - Decision trees and cheat sheets
🌐 Language Support
# English projects
Follow prompts/AI_CODING_ASSISTANT_EN.md
# 中文项目
遵循 prompts/AI_CODING_ASSISTANT_CN.md 的指导📖 Learn More
Architecture Overview
The library is built on a hierarchical structure with the following core classes:
BaseDataManager (Abstract)
├── FullListDataManager
└── CommonPagedDataManager (Abstract)
├── PagedDataManager
└── StackDataManagerCore Classes
1. BaseDataManager
Abstract base class for managing data collections with common CRUD operations.
Key Features:
- Data collection management with local caching
- CRUD operations with automatic local synchronization
- Data transformation support via
convertfunction - Equality checking via
checkEqualfunction - Service-based architecture for data operations
Properties:
service: CommonDataService- Data service instancecheckEqual: CheckEqual- Function to compare data itemsconvert?: DataConvert- Optional data transformation functionlist: Array<any>- Current dataset (read-only copy)
Methods:
save(data: any, isNew: boolean): Promise<void>- Save/update dataremove(item: any): Promise<void>- Delete dataappend(item: any): void- Add item to beginning of listreplace(item: any): void- Replace existing item with matching keyremoveItem(item: any): void- Remove item from local collection only
2. FullListDataManager
Concrete class inheriting from BaseDataManager for managing complete datasets.
Use Cases:
- Dropdown lists
- Static reference data
- Small to medium-sized complete datasets
- Configuration lists
Constructor:
protected constructor(
service: T,
keyField: string | CheckEqual,
options: ManagerOptions = null
)Additional Methods:
loadData(): Promise<void>- Load complete dataset from service using tagData as filter conditions
Example:
import { FullListDataManager } from '@ticatec/app-data-manager';
import { MyFullListDataService } from './services';
class CategoryManager extends FullListDataManager<MyFullListDataService> {
constructor() {
super(
new MyFullListDataService(),
'id',
{
tagData: { status: 'active', type: 'public' } // filter conditions for getList
}
);
}
}
const manager = new CategoryManager();
await manager.loadData(); // Uses tagData as filter conditions
console.log(manager.list); // Filtered category list3. CommonPagedDataManager
Abstract base class for paginated data management with comprehensive pagination support.
Constructor:
protected constructor(
service: T,
keyField: string | CheckEqual,
options: any = null
)Key Features:
- Pagination state management (pageNo, pageCount, totalCount)
- Query criteria handling with tagData-based initialization
- Configurable pagination parameters
- Abstract
processDataResultmethod for custom data processing
Static Configuration:
CommonPagedDataManager.setRowsPerPage(25)- Set default rows per pageCommonPagedDataManager.setRowsKey('rows')- Set rows parameter nameCommonPagedDataManager.setPageNoKey('page')- Set page parameter name
Properties:
criteria: any- Current query criteria (initialized from options.tagData or empty object)count: number- Total record count
Methods:
search(criteria: any): Promise<void>- Search with criteriasetPageNo(pageNo: number): Promise<void>- Navigate to specific pagesetRowsPage(rows: number): Promise<void>- Change page sizerefresh(): Promise<void>- Refresh current dataresetSearch(): Promise<void>- Reset to default criteria
4. PagedDataManager
Concrete implementation of CommonPagedDataManager for standard pagination.
Use Cases:
- Data tables with pagination
- Search results with page navigation
- Standard paginated lists
Additional Properties:
pageCount: number- Total number of pagespageNo: number- Current page number
Data Processing:
- Replaces entire dataset with new page data
- Simple and straightforward pagination
Constructor:
constructor(
service: T,
keyField: string | CheckEqual,
options: any = null
)Example:
import { PagedDataManager } from '@ticatec/app-data-manager';
import { MyPagingDataService } from './services';
class UserManager extends PagedDataManager<MyPagingDataService> {
constructor() {
super(
new MyPagingDataService(),
'userId',
{
tagData: { status: 'active' } // default criteria via tagData
}
);
}
}
const manager = new UserManager();
// Will search with default criteria from tagData { status: 'active' }
await manager.resetSearch();
console.log(`Page ${manager.pageNo} of ${manager.pageCount}`);
console.log(`Total users: ${manager.count}`);
console.log(manager.list); // Current page users
// Navigate to next page
await manager.setPageNo(2);
// Search with additional criteria
await manager.search({ status: 'active', role: 'admin' });5. StackDataManager
Concrete implementation of CommonPagedDataManager for stackable pagination ("infinite scroll").
Use Cases:
- Social media feeds
- Infinite scroll implementations
- "Load More" functionality
- Progressive data loading
Key Features:
- Accumulates data across pages
- Automatic duplicate prevention using
unionmethod loadMore()andhasMore()methods for progressive loading
Additional Methods:
loadMore(): Promise<void>- Load next page and append to existing datahasMore(): boolean- Check if more pages are available
Data Processing:
- Merges new data with existing dataset
- Prevents duplicates using
checkEqualfunction
Constructor:
constructor(
service: T,
keyField: string | CheckEqual,
options: any = null
)Example:
import { StackDataManager } from '@ticatec/app-data-manager';
import { MyPagingDataService } from './services';
class FeedManager extends StackDataManager<MyPagingDataService> {
constructor() {
super(
new MyPagingDataService(),
'postId',
{
tagData: { category: 'technology' } // default criteria via tagData
}
);
}
}
const manager = new FeedManager();
// Will search with default criteria from tagData { category: 'technology' }
await manager.resetSearch();
// Load more content
while (manager.hasMore()) {
await manager.loadMore();
console.log(`Loaded ${manager.list.length} posts`);
}
// Search with different criteria
await manager.search({ category: 'science', featured: true });Interface Definitions
IPagedDataManager
Interface defining the contract for paginated data management operations.
Properties:
list: Array<any>- Current dataset (read-only)count: number- Total record countpageNo: number- Current page numberpageCount: number- Total number of pagescriteria: any- Current query criteria
Methods:
refresh(): Promise<void>- Refresh current dataresetCriteria(): any- Reset search criteria to defaultresetSearch(): Promise<void>- Reset to default criteria and reloadsearch(params: any): Promise<void>- Search with new criteriasetRowsPage(rows: number): Promise<void>- Change page sizesetPageNo(value: number): Promise<void>- Navigate to specific page
Implementation:
PagedDataManagerimplements this interface for standard pagination
Example:
import { IPagedDataManager, PagedDataManager } from '@ticatec/app-data-manager';
class UserService extends PagingDataService {
constructor() {
super('/api/users');
}
}
// PagedDataManager implements IPagedDataManager
const userManager: IPagedDataManager = new PagedDataManager(
new UserService(),
'id'
);
await userManager.search({ status: 'active' });
console.log(`Page ${userManager.pageNo} of ${userManager.pageCount}`);
console.log(`Total: ${userManager.count} records`);Type Definitions
CheckEqual
type CheckEqual = (e1: any, e2: any) => boolean;Function to determine if two data items are equal (typically by comparing primary keys).
DataConvert
type DataConvert = (item: any, isNew: boolean) => any;Optional function to transform data items during save/load operations.
ManagerOptions
interface ManagerOptions {
convert?: DataConvert; // Data transformation function
fromTop?: boolean; // Add new items to top of list (default: true)
tagData?: any; // Default query criteria/filter conditions
}tagData Usage:
- For paginated managers: Used as default query criteria for searches
- For FullListDataManager: Used as filter conditions for the getList method
Advanced Usage
Custom Data Manager
import { BaseDataManager } from '@ticatec/app-data-manager';
class CustomDataManager extends BaseDataManager<MyDataService> {
constructor(service: MyDataService) {
super(service, 'id', {
convert: (item, isNew) => ({
...item,
timestamp: isNew ? Date.now() : item.timestamp
}),
fromTop: true
});
}
// Custom business logic
async archiveItem(item: any): Promise<void> {
const archived = { ...item, archived: true };
await this.save(archived, false);
}
}Service Implementation Example
import { PagingDataService } from '@ticatec/app-data-service';
class MyPagingService extends PagingDataService {
constructor() {
super('/api/users');
}
}Best Practices
Choose the Right Manager:
- Use
FullListDataManagerfor small, static datasets - Use
PagedDataManagerfor traditional paginated tables - Use
StackDataManagerfor infinite scroll or feed-like interfaces
- Use
Implement Proper Equality Checking:
// Good: Use unique identifiers const manager = new PagedDataManager(service, 'id'); // Better: Custom comparison for complex keys const manager = new PagedDataManager(service, (a, b) => a.companyId === b.companyId && a.userId === b.userId );Handle Errors Gracefully:
try { await manager.search({ query: 'user input' }); } catch (error) { console.error('Search failed:', error); // Handle error appropriately }Use Data Conversion for Consistency:
const options = { convert: (item, isNew) => ({ ...item, createdAt: isNew ? new Date().toISOString() : item.createdAt, updatedAt: new Date().toISOString() }) };
Dependencies
- @ticatec/app-data-service ^2.0.0 - Data service interfaces and base implementations (peer dependency)
- @ticatec/restful_service_api ^0.5.0 - RESTful API service (peer dependency)
- @ticatec/enhanced-utils - Utility functions including array extensions
Performance Optimization Tips
Use appropriate manager for your data size:
FullListDataManager: Best for datasets under 1,000 recordsPagedDataManager: Ideal for large datasets with paginationStackDataManager: Perfect for infinite scroll with frequent updates
Optimize page size:
// Configure optimal page size based on your data complexity CommonPagedDataManager.setRowsPerPage(50); // Default is 25Use efficient equality checks:
// Fast: Single field comparison const fastManager = new PagedDataManager(service, 'id'); // Slower but necessary: Multi-field comparison const complexManager = new PagedDataManager(service, (a, b) => a.companyId === b.companyId && a.userId === b.userId );Implement proper error boundaries:
try { await manager.search({ query: userKeyword }); } catch (error) { if (error.response?.status === 401) { // Handle authentication error } else if (error.response?.status === 429) { // Handle rate limiting } else { // Handle other errors } }
FAQ
Q: What's the difference between tagData and search criteria?
A: tagData in options sets default/fixed filter criteria that persist across searches, while criteria passed to search() are combined with tagData for that specific search.
Q: How do I clear all data?
A: Call resetSearch() to reset to default criteria and reload, or create a new manager instance.
Q: Can I use multiple managers for the same data type?
A: Yes, you can create multiple manager instances with different tagData configurations for the same service.
Q: How do I handle concurrent searches?
A: The manager processes searches sequentially. If you need cancellation support, implement abort controllers in your service layer.
Q: Is the data cached?
A: Yes, each manager maintains an in-memory cache. Use refresh() to reload data from the server.
Browser Support
- Chrome/Edge 88+
- Firefox 85+
- Safari 14+
- Node.js 14+
Contributing
Issues and pull requests are welcome. Please ensure:
- All tests pass
- Code follows TypeScript best practices
- Documentation is updated for new features
- Examples are provided for new functionality
License
Copyright © 2023 Ticatec. All rights reserved.
This library is released under the MIT License. See LICENSE file for details.
Contact
- Email: [email protected]
- GitHub: https://github.com/ticatec/app-data-manager
- Issues: https://github.com/ticatec/app-data-manager/issues
