The Repository class provides a complete API for interacting with Shopware entities, including search, create, update, and delete operations.
Creating a Repository
import { data } from '@shopware-ag/admin-sdk';
const productRepository = data.repository('product');
Methods
search()
Search for entities using criteria.
Search criteria object defining filters, sorting, pagination, and associations
Optional API context for the request (authentication, language, etc.)
result
Promise<EntityCollection<EntityName> | null>
Returns a promise that resolves to an EntityCollection or null
Example
import { data } from '@shopware-ag/admin-sdk';
const productRepository = data.repository('product');
const criteria = new data.Classes.Criteria(1, 25);
// Add filters
criteria.addFilter(
data.Classes.Criteria.equals('active', true)
);
// Add sorting
criteria.addSorting(
data.Classes.Criteria.sort('name', 'ASC')
);
// Add associations
criteria.addAssociation('manufacturer');
// Execute search
const products = await productRepository.search(criteria);
console.log(`Found ${products.total} products`);
products.forEach(product => {
console.log(product.name);
});
get()
Retrieve a single entity by ID.
The entity ID to retrieve
Optional API context for the request
Optional criteria to load associations or specific fields
result
Promise<Entity<EntityName> | null>
Returns a promise that resolves to an Entity or null if not found
Example
const productRepository = data.repository('product');
// Get product with associations
const criteria = new data.Classes.Criteria();
criteria.addAssociation('categories');
criteria.addAssociation('manufacturer');
const product = await productRepository.get(
'product-id-here',
undefined,
criteria
);
if (product) {
console.log('Product:', product.name);
console.log('Categories:', product.categories);
}
save()
Save changes to an entity.
entity
Entity<EntityName>
required
The entity to save (can be new or existing)
Optional API context for the request
Returns a promise that resolves when the save is complete
Example
const productRepository = data.repository('product');
// Get and modify entity
const product = await productRepository.get('product-id-here');
product.name = 'Updated Product Name';
product.price = [{
currencyId: 'currency-id',
gross: 99.99,
net: 84.03,
linked: true
}];
// Save changes
await productRepository.save(product);
console.log('Product saved successfully');
create()
Create a new entity.
Optional API context for the request
Optional ID for the new entity (auto-generated if not provided)
result
Promise<Entity<EntityName> | null>
Returns a promise that resolves to a new Entity instance
Example
const productRepository = data.repository('product');
// Create new product
const newProduct = await productRepository.create();
// Set properties
newProduct.name = 'New Product';
newProduct.productNumber = 'PROD-001';
newProduct.stock = 100;
newProduct.taxId = 'tax-id-here';
newProduct.price = [{
currencyId: 'currency-id',
gross: 49.99,
net: 42.01,
linked: true
}];
// Save the new entity
await productRepository.save(newProduct);
console.log('New product created:', newProduct.id);
delete()
Delete an entity by ID.
The ID of the entity to delete
Optional API context for the request
Returns a promise that resolves when the deletion is complete
Example
const productRepository = data.repository('product');
// Delete product
await productRepository.delete('product-id-here');
console.log('Product deleted');
clone()
Clone an existing entity.
The ID of the entity to clone
Optional API context for the request
Optional behavior configuration for the clone operation
Returns a promise that resolves to the cloned entity
Example
const productRepository = data.repository('product');
// Clone a product
const clonedProduct = await productRepository.clone('product-id-here');
console.log('Product cloned:', clonedProduct);
hasChanges()
Check if an entity has unsaved changes.
entity
Entity<EntityName>
required
The entity to check for changes
Returns true if the entity has been modified
Example
const product = await productRepository.get('product-id-here');
product.name = 'Modified Name';
const isDirty = await productRepository.hasChanges(product);
console.log('Has changes:', isDirty); // true
saveAll()
Save multiple entities at once.
entities
EntityCollection<EntityName>
required
Collection of entities to save
Optional API context for the request
Returns a promise that resolves when all entities are saved
Example
const productRepository = data.repository('product');
// Search and modify multiple products
const criteria = new data.Classes.Criteria(1, 10);
const products = await productRepository.search(criteria);
// Modify all products
products.forEach(product => {
product.active = true;
});
// Save all changes
await productRepository.saveAll(products);
console.log('All products saved');
Criteria Builder
The Criteria class provides a fluent API for building complex queries:
Filters
const criteria = new data.Classes.Criteria();
// Equals filter
criteria.addFilter(data.Classes.Criteria.equals('active', true));
// Contains filter
criteria.addFilter(data.Classes.Criteria.contains('name', 'Product'));
// Range filter
criteria.addFilter(data.Classes.Criteria.range('stock', { gte: 10, lte: 100 }));
// Multiple filters (AND)
criteria.addFilter(
data.Classes.Criteria.multi('AND', [
data.Classes.Criteria.equals('active', true),
data.Classes.Criteria.range('price', { gte: 10 })
])
);
Sorting
const criteria = new data.Classes.Criteria();
// Simple sorting
criteria.addSorting(data.Classes.Criteria.sort('name', 'ASC'));
// Natural sorting (for strings with numbers)
criteria.addSorting(data.Classes.Criteria.naturalSorting('productNumber', 'ASC'));
// Count sorting (sort by association count)
criteria.addSorting(data.Classes.Criteria.countSorting('categories', 'DESC'));
// Page 1, 25 items per page
const criteria = new data.Classes.Criteria(1, 25);
// Or set later
criteria.setPage(2);
criteria.setLimit(50);
Associations
const criteria = new data.Classes.Criteria();
// Load simple association
criteria.addAssociation('manufacturer');
// Load nested associations
criteria.addAssociation('categories.media');
// Configure association criteria
const categoryCriteria = criteria.getAssociation('categories');
categoryCriteria.addFilter(data.Classes.Criteria.equals('active', true));
categoryCriteria.addSorting(data.Classes.Criteria.sort('name', 'ASC'));
Aggregations
const criteria = new data.Classes.Criteria();
// Count aggregation
criteria.addAggregation(data.Classes.Criteria.count('total-count', 'id'));
// Sum aggregation
criteria.addAggregation(data.Classes.Criteria.sum('total-stock', 'stock'));
// Average aggregation
criteria.addAggregation(data.Classes.Criteria.avg('avg-price', 'price'));
// Terms aggregation
criteria.addAggregation(
data.Classes.Criteria.terms('manufacturer-ids', 'manufacturerId', 10)
);
Type Definitions
ApiContext
interface ApiContext {
apiPath?: string;
apiResourcePath?: string;
assetsPath?: string;
authToken?: string;
basePath?: string;
pathInfo?: string;
inheritance?: boolean;
installationPath?: string;
languageId?: string;
language?: string;
apiVersion?: number;
liveVersionId?: string;
systemLanguageId?: string;
}
TotalCountMode
enum TotalCountMode {
NO_TOTAL_COUNT = 0, // Fastest, no total count
EXACT_TOTAL_COUNT = 1, // Slow, exact count
PAGINATION_TOTAL_COUNT = 2 // Fast, limit * 5 + 1
}
Best Practices
Use TotalCountMode.NO_TOTAL_COUNT when you don’t need pagination for better performance.
Always check if entities exist before operating on them, as repository methods can return null.
Use setTitle() on criteria to help debug searches in the browser’s network tab.