feat: implement bulk contact action selector for improved flexibility in bulk operations

This commit is contained in:
Dries Augustyns
2026-05-10 10:40:40 +02:00
parent 7658a59b5d
commit de6335e999
8 changed files with 713 additions and 355 deletions
+15 -3
View File
@@ -96,9 +96,21 @@ export const ContactSchemas = {
subscribed: z.boolean().default(true),
data: jsonSchema.optional(),
}),
bulkAction: z.object({
contactIds: z.array(uuid).min(1).max(1000),
}),
bulkAction: z.discriminatedUnion('mode', [
z.object({
mode: z.literal('ids'),
contactIds: z.array(uuid).min(1).max(1000),
}),
z.object({
mode: z.literal('query'),
filter: z
.object({
search: z.string().max(255).optional(),
})
.default({}),
excludeIds: z.array(uuid).max(10000).optional(),
}),
]),
lookup: z.object({
emails: z.array(z.string().email()).min(1).max(500),
}),
+12 -1
View File
@@ -12,12 +12,23 @@ export interface ContactImportJobData {
filename: string;
}
/**
* Selector describing which contacts a bulk action should target.
* - `ids`: explicit list, hard-capped at 1000.
* - `query`: every contact matching the filter, optionally excluding specific ids.
* Snapshot semantics: the worker iterates current matches at execution time, so
* contacts created after the job is queued may or may not be included.
*/
export type BulkContactActionSelector =
| {mode: 'ids'; contactIds: string[]}
| {mode: 'query'; filter: {search?: string}; excludeIds?: string[]};
/**
* Job data for bulk contact actions (subscribe, unsubscribe, delete)
* Used by: bulkContactQueue worker
*/
export interface BulkContactActionJobData {
projectId: string;
contactIds: string[];
operation: 'subscribe' | 'unsubscribe' | 'delete';
selector: BulkContactActionSelector;
}