Migration Guide
This guide helps you migrate between dcupl SDK versions and adopt new API patterns. The SDK maintains backward compatibility, so migrations are optional but recommended for better developer experience.
Query API Migration (v2.1+)
The query refactor introduces clearer method names while maintaining 100% backward compatibility. Old methods continue to work, but new methods provide better IntelliSense and type safety.
Migration Strategy
You don't need to migrate everything at once:
- Continue using old methods (they're not going away in v2.x)
- Adopt new methods incrementally as you work on code
- Use new methods for all new code
Type Aliases
import { DcuplQuery, DcuplQueryGroup, DcuplGlobalQueryOptions } from '@dcupl/common';
const condition: DcuplQuery = { operator: 'eq', attribute: 'status', value: 'active' };
const group: DcuplQueryGroup = { groupType: 'and', queries: [condition] };import { QueryCondition, QueryConditionGroup, QueryExecutionContext } from '@dcupl/common';
const condition: QueryCondition = { operator: 'eq', attribute: 'status', value: 'active' };
const group: QueryConditionGroup = { groupType: 'and', queries: [condition] };Adding Query Conditions
// Magic applyQuery with mode options
builder.applyQuery(condition, { mode: 'add' });
builder.applyQuery([condition1, condition2], { mode: 'add' });
builder.applyQuery(group, { mode: 'add' });// Explicit methods that reveal intent
builder.addCondition(condition);
builder.addCondition([condition1, condition2]);
builder.addGroup(group);Replacing Query Conditions
builder.applyQuery(condition, { mode: 'set' });
list.catalog.query.apply(condition, { mode: 'set' });builder.setCondition(condition);
list.catalog.query.setCondition(condition);State Management
builder.reset();
builder.removeAllQueries();
builder.getQuery();builder.clear();
builder.clearConditions();
builder.getCurrentQuery();Executing Queries
const items = list.catalog.query.execute();
const limited = list.catalog.query.execute({ count: 10 });
const query = list.catalog.query.get();const items = list.catalog.query.items();
const limited = list.catalog.query.items({ count: 10 });
const first = list.catalog.query.first();
const exists = list.catalog.query.any();
const total = list.catalog.query.count();
const query = list.catalog.query.current();Complete Migration Example
const builder = new DcuplQueryBuilder();
builder.init({ modelKey: 'Product' });
builder.applyQuery({ operator: 'eq', attribute: 'status', value: 'active' }, { mode: 'add' });
builder.applyQuery({ operator: 'gte', attribute: 'price', value: 100 }, { mode: 'add' });
builder.applyQuery(
{
groupKey: 'categories',
groupType: 'or',
queries: [
{ operator: 'eq', attribute: 'category', value: 'electronics' },
{ operator: 'eq', attribute: 'category', value: 'books' },
],
},
{ mode: 'add' }
);
const query = builder.getQuery();
const attrs = builder.getQueryAttributes();const builder = new DcuplQueryBuilder();
builder.init({ modelKey: 'Product' });
builder.addCondition({ operator: 'eq', attribute: 'status', value: 'active' });
builder.addCondition({ operator: 'gte', attribute: 'price', value: 100 });
builder.addGroup({
groupKey: 'categories',
groupType: 'or',
queries: [
{ operator: 'eq', attribute: 'category', value: 'electronics' },
{ operator: 'eq', attribute: 'category', value: 'books' },
],
});
const query = builder.getCurrentQuery();
const attrs = builder.getAttributeNames();
const count = builder.getConditionCount();
const isEmpty = builder.isEmpty();Interactive List Migration
function applyStatusFilter(status: string) {
list.catalog.query.apply({ operator: 'eq', attribute: 'status', value: status }, { mode: 'add' });
return list.catalog.query.execute();
}
function clearFilters() {
list.catalog.query.reset();
return list.catalog.query.execute();
}
function getFirstProduct() {
const results = list.catalog.query.execute({ count: 1 });
return results[0];
}function applyStatusFilter(status: string) {
list.catalog.query.addCondition({ operator: 'eq', attribute: 'status', value: status });
return list.catalog.query.items();
}
function clearFilters() {
list.catalog.query.clear();
return list.catalog.query.items();
}
function getFirstProduct() {
return list.catalog.query.first();
}
// Additional new capabilities
function hasProducts() {
return list.catalog.query.any();
}
function getProductCount() {
return list.catalog.query.count();
}
function hasFilters() {
return !list.catalog.query.isEmpty();
}Quick Reference Tables
DcuplQueryBuilder Methods
| Old Method | New Method | Purpose |
|---|---|---|
getQueryAttributes() |
getAttributeNames() |
Get attribute name strings |
extractQueryAttributes() |
getAttributeDetails() |
Get detailed attribute info |
applyQuery(..., {mode:'add'}) |
addCondition() |
Add condition(s) |
applyQuery(group, {mode:'add'}) |
addGroup() |
Add query group |
applyQuery(..., {mode:'set'}) |
setCondition() |
Replace condition(s) |
reset() |
clear() |
Full reset |
removeAllQueries() |
clearConditions() |
Remove conditions only |
getQuery() |
getCurrentQuery() |
Get current state |
hasQueryGroup() |
hasGroup() |
Check group exists |
| - | isEmpty() |
Check if empty |
| - | hasCondition() |
Check condition exists |
| - | getConditionCount() |
Count conditions |
CatalogApi Methods
| Old Method | New Method | Purpose |
|---|---|---|
apply(..., {mode:'add'}) |
addCondition() |
Add condition(s) |
apply(group, {mode:'add'}) |
addGroup() |
Add query group |
apply(..., {mode:'set'}) |
setCondition() |
Replace condition(s) |
remove(condition) |
removeCondition() |
Remove condition(s) |
remove({groupKey}) |
removeGroup() |
Remove group |
reset() |
clear() |
Clear all conditions |
get() |
current() |
Get current query |
execute() |
items() |
Get all results |
| - | first() |
Get first result |
| - | any() |
Check if results exist |
| - | count() |
Count results |
| - | isEmpty() |
Check if empty |
Benefits of New API
Old API Challenges:
applyQuery()- Implicit behavior based on parameters- Mode options - Need to remember
{ mode: 'add' }vs{ mode: 'set' } - Limited inspection - Hard to introspect query state
New API Advantages:
- Explicit methods -
addCondition()vssetCondition()clearly show intent - Intuitive names -
first(),count(),any()match expectations - Flexible arguments - Methods accept both single items and arrays
- Rich inspection - Many methods to understand query state
- Better IntelliSense - Comprehensive documentation in IDE
- No breaking changes - Old methods still work
Deprecation Timeline
Current Status: All old methods are marked @deprecated in JSDoc but remain fully functional.
Future: Old methods will be removed in a future versions, but:
- Ample warning will be provided
- Old methods will be supported throughout v2.x lifecycle
Recommendation: Start using new methods for new code, migrate existing code opportunistically.
What's Next?
- Query Operators - Complete operator reference
- Filtering - Query fundamentals
- Deep Queries - Advanced querying
- TypeScript Guide - Type safety patterns