@unchainedshop/core-assortments 5.0.0-alpha.4 → 5.0.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,7 +25,7 @@ export declare const configureAssortmentProductsModule: ({ AssortmentProducts, i
25
25
  productId: string;
26
26
  assortmentIds: string[];
27
27
  }) => Promise<string[]>;
28
- create: (doc: Omit<AssortmentProduct, "_id" | "created" | "sortKey"> & Partial<Pick<AssortmentProduct, "_id" | "created" | "sortKey">>, options?: {
28
+ create: (doc: Omit<AssortmentProduct, "_id" | "created" | "sortKey" | "tags"> & Partial<Pick<AssortmentProduct, "_id" | "created" | "sortKey" | "tags">>, options?: {
29
29
  skipInvalidation?: boolean;
30
30
  }) => Promise<mongodb.WithId<AssortmentProduct> | null>;
31
31
  delete: (assortmentProductId: string, options?: {
@@ -52,6 +52,21 @@ export declare const configureAssortmentsModule: (moduleInput: ModuleInput<Assor
52
52
  skipInvalidation?: boolean;
53
53
  }) => Promise<mongodb.WithId<Assortment> | null>;
54
54
  invalidateCache: InvalidateCacheFn;
55
+ bulkDelete: (assortmentIds: string[]) => Promise<{
56
+ successIds: string[];
57
+ failedIds: string[];
58
+ }>;
59
+ bulkSetActive: (assortmentIds: string[], isActive: boolean) => Promise<{
60
+ successIds: string[];
61
+ failedIds: string[];
62
+ }>;
63
+ bulkUpdateTags: (assortmentIds: string[], { add, remove }: {
64
+ add?: string[];
65
+ remove?: string[];
66
+ }) => Promise<{
67
+ successIds: string[];
68
+ failedIds: string[];
69
+ }>;
55
70
  search: {
56
71
  findFilteredAssortments: ({ limit, offset, assortmentIds, assortmentSelector, sort, }: {
57
72
  assortmentIds: string[];
@@ -184,7 +199,7 @@ export declare const configureAssortmentsModule: (moduleInput: ModuleInput<Assor
184
199
  productId: string;
185
200
  assortmentIds: string[];
186
201
  }) => Promise<string[]>;
187
- create: (doc: Omit<AssortmentProduct, "_id" | "created" | "sortKey"> & Partial<Pick<AssortmentProduct, "_id" | "created" | "sortKey">>, options?: {
202
+ create: (doc: Omit<AssortmentProduct, "_id" | "created" | "sortKey" | "tags"> & Partial<Pick<AssortmentProduct, "_id" | "created" | "sortKey" | "tags">>, options?: {
188
203
  skipInvalidation?: boolean;
189
204
  }) => Promise<mongodb.WithId<AssortmentProduct> | null>;
190
205
  delete: (assortmentProductId: string, options?: {
@@ -1,4 +1,4 @@
1
- import { SortDirection } from '@unchainedshop/utils';
1
+ import { executeBulkOperation, SortDirection } from '@unchainedshop/utils';
2
2
  import { emit, registerEvents } from '@unchainedshop/events';
3
3
  import { generateDbFilterById, findPreservingIds, buildSortOptions, mongodb, generateDbObjectId, } from '@unchainedshop/mongodb';
4
4
  import { createLogger } from '@unchainedshop/logger';
@@ -123,6 +123,42 @@ export const configureAssortmentsModule = async (moduleInput) => {
123
123
  AssortmentTexts,
124
124
  });
125
125
  const assortmentMedia = await configureAssortmentMediaModule(moduleInput);
126
+ const updateAssortment = async (assortmentId, doc, options) => {
127
+ const assortment = await Assortments.findOneAndUpdate(generateDbFilterById(assortmentId), {
128
+ $set: {
129
+ updated: new Date(),
130
+ ...doc,
131
+ },
132
+ }, { returnDocument: 'after' });
133
+ if (!assortment)
134
+ return null;
135
+ await emit('ASSORTMENT_UPDATE', { assortmentId });
136
+ if (!options?.skipInvalidation) {
137
+ await invalidateCache({ assortmentIds: [assortmentId] });
138
+ }
139
+ return assortment;
140
+ };
141
+ const deleteAssortment = async (assortmentId, options) => {
142
+ await assortmentLinks.deleteMany({
143
+ $or: [{ parentAssortmentId: assortmentId }, { childAssortmentId: assortmentId }],
144
+ }, { skipInvalidation: true });
145
+ await assortmentProducts.deleteMany({ assortmentId }, { skipInvalidation: true });
146
+ await assortmentFilters.deleteMany({ assortmentId });
147
+ await assortmentTexts.deleteMany({ assortmentId });
148
+ await assortmentMedia.deleteMediaFiles({ assortmentId });
149
+ const deletedAssortment = await Assortments.findOneAndUpdate(generateDbFilterById(assortmentId), {
150
+ $set: {
151
+ deleted: new Date(),
152
+ },
153
+ }, { returnDocument: 'after' });
154
+ if (!deletedAssortment)
155
+ return null;
156
+ if (!options?.skipInvalidation) {
157
+ await invalidateCache({}, { skipUpstreamTraversal: true });
158
+ }
159
+ await emit('ASSORTMENT_REMOVE', { assortmentId });
160
+ return deletedAssortment;
161
+ };
126
162
  return {
127
163
  findAssortment: async ({ assortmentId, slug }) => {
128
164
  let selector = {};
@@ -212,43 +248,39 @@ export const configureAssortmentsModule = async (moduleInput) => {
212
248
  await emit('ASSORTMENT_CREATE', { assortment });
213
249
  return assortment;
214
250
  },
215
- update: async (assortmentId, doc, options) => {
216
- const assortment = await Assortments.findOneAndUpdate(generateDbFilterById(assortmentId), {
217
- $set: {
218
- updated: new Date(),
219
- ...doc,
220
- },
221
- }, { returnDocument: 'after' });
222
- if (!assortment)
223
- return null;
224
- await emit('ASSORTMENT_UPDATE', { assortmentId });
225
- if (!options?.skipInvalidation) {
226
- await invalidateCache({ assortmentIds: [assortmentId] });
227
- }
228
- return assortment;
251
+ update: updateAssortment,
252
+ delete: deleteAssortment,
253
+ invalidateCache,
254
+ bulkDelete: async (assortmentIds) => {
255
+ return executeBulkOperation(assortmentIds, async (assortmentId) => {
256
+ const assortment = await Assortments.findOne({ _id: assortmentId, deleted: null }, {});
257
+ if (!assortment)
258
+ throw new Error('not-found');
259
+ if (!(await deleteAssortment(assortmentId))) {
260
+ throw new Error('delete-failed');
261
+ }
262
+ });
229
263
  },
230
- delete: async (assortmentId, options) => {
231
- await assortmentLinks.deleteMany({
232
- $or: [{ parentAssortmentId: assortmentId }, { childAssortmentId: assortmentId }],
233
- }, { skipInvalidation: true });
234
- await assortmentProducts.deleteMany({ assortmentId }, { skipInvalidation: true });
235
- await assortmentFilters.deleteMany({ assortmentId });
236
- await assortmentTexts.deleteMany({ assortmentId });
237
- await assortmentMedia.deleteMediaFiles({ assortmentId });
238
- const deletedAssortment = await Assortments.findOneAndUpdate(generateDbFilterById(assortmentId), {
239
- $set: {
240
- deleted: new Date(),
241
- },
242
- }, { returnDocument: 'after' });
243
- if (!deletedAssortment)
244
- return null;
245
- if (!options?.skipInvalidation) {
246
- await invalidateCache({}, { skipUpstreamTraversal: true });
247
- }
248
- await emit('ASSORTMENT_REMOVE', { assortmentId });
249
- return deletedAssortment;
264
+ bulkSetActive: async (assortmentIds, isActive) => executeBulkOperation(assortmentIds, async (assortmentId) => {
265
+ const assortment = await Assortments.findOne({ _id: assortmentId, deleted: null }, {});
266
+ if (!assortment)
267
+ throw new Error('not-found');
268
+ await updateAssortment(assortmentId, { isActive });
269
+ }),
270
+ bulkUpdateTags: async (assortmentIds, { add = [], remove = [] }) => {
271
+ const tagsToRemove = new Set(remove);
272
+ return executeBulkOperation(assortmentIds, async (assortmentId) => {
273
+ const assortment = await Assortments.findOne({ _id: assortmentId, deleted: null }, {});
274
+ if (!assortment)
275
+ throw new Error('not-found');
276
+ const tags = (assortment.tags || []).filter((tag) => !tagsToRemove.has(tag));
277
+ for (const tag of add) {
278
+ if (!tags.includes(tag))
279
+ tags.push(tag);
280
+ }
281
+ await updateAssortment(assortmentId, { tags });
282
+ });
250
283
  },
251
- invalidateCache,
252
284
  search: {
253
285
  findFilteredAssortments: async ({ limit, offset, assortmentIds, assortmentSelector, sort, }) => {
254
286
  const assortments = await findPreservingIds(Assortments)(assortmentSelector, assortmentIds, {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@unchainedshop/core-assortments",
3
3
  "description": "Assortment and category management module for the Unchained Engine",
4
- "version": "5.0.0-alpha.4",
4
+ "version": "5.0.0-alpha.5",
5
5
  "main": "lib/assortments-index.js",
6
6
  "types": "lib/assortments-index.d.ts",
7
7
  "type": "module",
@@ -35,10 +35,10 @@
35
35
  },
36
36
  "homepage": "https://github.com/unchainedshop/unchained#readme",
37
37
  "dependencies": {
38
- "@unchainedshop/events": "^5.0.0-alpha.1",
39
- "@unchainedshop/logger": "^5.0.0-alpha.1",
40
- "@unchainedshop/mongodb": "^5.0.0-alpha.1",
41
- "@unchainedshop/utils": "^5.0.0-alpha.1"
38
+ "@unchainedshop/events": "^5.0.0-alpha.5",
39
+ "@unchainedshop/logger": "^5.0.0-alpha.5",
40
+ "@unchainedshop/mongodb": "^5.0.0-alpha.5",
41
+ "@unchainedshop/utils": "^5.0.0-alpha.5"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^26.2.0",