Skip to main content

EntityDuplicator

EntityDuplicator

An EntityDuplicator is used to define the logic for duplicating entities when the duplicateEntity mutation is called. This allows you to add support for duplication of both core and custom entities.

Example

src/config/custom-collection-duplicator.ts
import { Collection, LanguageCode, Permission
EntityDuplicator, TransactionalConnection, CollectionService } from '@vendure/core';

let collectionService: CollectionService;
let connection: TransactionalConnection;

// This is just an example - we already ship with a built-in duplicator for Collections.
const customCollectionDuplicator = new EntityDuplicator({
code: 'custom-collection-duplicator',
description: [{ languageCode: LanguageCode.en, value: 'Custom collection duplicator' }],
args: {
throwError: {
type: 'boolean',
defaultValue: false,
},
},
forEntities: ['Collection'],
requiresPermission: [Permission.UpdateCollection],
init(injector) {
collectionService = injector.get(CollectionService);
connection = injector.get(TransactionalConnection);
},
duplicate: async input => {
const { ctx, id, args } = input;

const original = await connection.getEntityOrThrow(ctx, Collection, id, {
relations: {
assets: true,
featuredAsset: true,
},
});
const newCollection = await collectionService.create(ctx, {
isPrivate: original.isPrivate,
customFields: original.customFields,
assetIds: original.assets.map(a => a.id),
featuredAssetId: original.featuredAsset?.id,
parentId: original.parentId,
filters: original.filters.map(f => ({
code: f.code,
arguments: f.args,
})),
inheritFilters: original.inheritFilters,
translations: original.translations.map(t => ({
languageCode: t.languageCode,
name: `${t.name} (copy)`,
slug: `${t.slug}-copy`,
description: t.description,
customFields: t.customFields,
})),
});

if (args.throwError) {
// If an error is thrown at any point during the duplication process, the entire
// transaction will get automatically rolled back, and the mutation will return
// an ErrorResponse containing the error message.
throw new Error('Dummy error');
}

return newCollection;
},
});

The duplicator then gets passed to your VendureConfig object:

src/vendure-config.ts
import { VendureConfig, defaultEntityDuplicators } from '@vendure/core';
import { customCollectionDuplicator } from './config/custom-collection-duplicator';

export const config: VendureConfig = {
// ...
entityOptions: {
entityDuplicators: [
...defaultEntityDuplicators,
customCollectionDuplicator,
],
},
};
Signature
class EntityDuplicator<T extends ConfigArgs = ConfigArgs> extends ConfigurableOperationDef<T> {
constructor(config: EntityDuplicatorConfig<T>)
duplicate(input: {
ctx: RequestContext;
entityName: string;
id: ID;
args: ConfigArg[];
}) => Promise<VendureEntity>;
}

constructor

method
(config: EntityDuplicatorConfig<T>) => EntityDuplicator

duplicate

method
(input: { ctx: RequestContext; entityName: string; id: ID; args: ConfigArg[]; }) => Promise<VendureEntity>

DuplicateEntityFn

A function which performs the duplication of an entity.

Signature
type DuplicateEntityFn<T extends ConfigArgs> = (input: {
ctx: RequestContext;
entityName: string;
id: ID;
args: ConfigArgValues<T>;
}) => Promise<VendureEntity>

EntityDuplicatorConfig

Configuration for creating a new EntityDuplicator.

Signature
interface EntityDuplicatorConfig<T extends ConfigArgs> extends ConfigurableOperationDefOptions<T> {
requiresPermission: Array<Permission | string> | Permission | string;
forEntities: string[];
duplicate: DuplicateEntityFn<T>;
}

requiresPermission

property
Array<Permission | string> | Permission | string

The permissions required in order to execute this duplicator. If an array is passed, then the administrator must have at least one of the permissions in the array.

forEntities

property
string[]

The entities for which this duplicator is able to duplicate.

duplicate

The function which performs the duplication.

Example

duplicate: async input => {
const { ctx, id, args } = input;

// perform the duplication logic here

return newEntity;
}