@unchainedshop/core-products 5.0.0-alpha.3 → 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.
|
@@ -41,11 +41,13 @@ export const ProductsCollection = async (db) => {
|
|
|
41
41
|
},
|
|
42
42
|
]);
|
|
43
43
|
await buildDbIndexes(Products, [
|
|
44
|
-
{ index: {
|
|
44
|
+
{ index: { status: 1, sequence: 1, published: -1 } },
|
|
45
45
|
{ index: { slugs: 1 } },
|
|
46
46
|
{ index: { tags: 1 } },
|
|
47
47
|
{ index: { 'warehousing.sku': 1 }, options: { sparse: true } },
|
|
48
|
-
|
|
48
|
+
{ index: { 'bundleItems.productId': 1 }, options: { sparse: true } },
|
|
49
|
+
{ index: { 'proxy.assignments.productId': 1 }, options: { sparse: true } },
|
|
50
|
+
], { rebuild: false });
|
|
49
51
|
await buildDbIndexes(ProductTexts, [
|
|
50
52
|
{ index: { productId: 1 } },
|
|
51
53
|
{ index: { slug: 1 } },
|
|
@@ -54,7 +54,7 @@ export const configureProductMediaModule = async ({ db }) => {
|
|
|
54
54
|
const mediaList = ProductMedias.find(selector, {
|
|
55
55
|
skip: offset,
|
|
56
56
|
limit,
|
|
57
|
-
sort: { sortKey: 1 },
|
|
57
|
+
sort: { sortKey: 1, _id: 1 },
|
|
58
58
|
...options,
|
|
59
59
|
});
|
|
60
60
|
return mediaList.toArray();
|
|
@@ -64,7 +64,7 @@ export const configureProductMediaModule = async ({ db }) => {
|
|
|
64
64
|
const lastProductMedia = (await ProductMedias.findOne({
|
|
65
65
|
productId: doc.productId,
|
|
66
66
|
}, {
|
|
67
|
-
sort: { sortKey: -1 },
|
|
67
|
+
sort: { sortKey: -1, _id: -1 },
|
|
68
68
|
})) || { sortKey: 0 };
|
|
69
69
|
sortKey = lastProductMedia.sortKey + 1;
|
|
70
70
|
}
|
|
@@ -123,7 +123,7 @@ export const configureProductMediaModule = async ({ db }) => {
|
|
|
123
123
|
}));
|
|
124
124
|
const productMedias = await ProductMedias.find({
|
|
125
125
|
_id: { $in: changedProductMediaIds },
|
|
126
|
-
}, { sort: { sortKey: 1 } }).toArray();
|
|
126
|
+
}, { sort: { sortKey: 1, _id: 1 } }).toArray();
|
|
127
127
|
await emit('PRODUCT_REORDER_MEDIA', { productMedias });
|
|
128
128
|
return productMedias;
|
|
129
129
|
},
|
|
@@ -108,7 +108,7 @@ export const configureProductPricesModule = ({ proxyProducts, db, }) => {
|
|
|
108
108
|
],
|
|
109
109
|
timestamp: { $lte: referenceDate },
|
|
110
110
|
expiresAt: { $gte: referenceDate },
|
|
111
|
-
}, { sort: { timestamp: -1 } });
|
|
111
|
+
}, { sort: { timestamp: -1, _id: -1 } });
|
|
112
112
|
if (!mostRecentCurrencyRate)
|
|
113
113
|
return null;
|
|
114
114
|
const rate = normalizeRate(baseCurrency, quoteCurrency, mostRecentCurrencyRate);
|
|
@@ -119,6 +119,21 @@ export declare const configureProductsModule: (moduleInput: ModuleInput<Products
|
|
|
119
119
|
}) => Promise<number>;
|
|
120
120
|
publish: (product: Product) => Promise<boolean>;
|
|
121
121
|
unpublish: (product: Product) => Promise<boolean>;
|
|
122
|
+
bulkPublish: (productIds: string[]) => Promise<{
|
|
123
|
+
successIds: string[];
|
|
124
|
+
failedIds: string[];
|
|
125
|
+
}>;
|
|
126
|
+
bulkUnpublish: (productIds: string[]) => Promise<{
|
|
127
|
+
successIds: string[];
|
|
128
|
+
failedIds: string[];
|
|
129
|
+
}>;
|
|
130
|
+
bulkUpdateTags: (productIds: string[], { add, remove }: {
|
|
131
|
+
add?: string[];
|
|
132
|
+
remove?: string[];
|
|
133
|
+
}) => Promise<{
|
|
134
|
+
successIds: string[];
|
|
135
|
+
failedIds: string[];
|
|
136
|
+
}>;
|
|
122
137
|
assignments: {
|
|
123
138
|
addProxyAssignment: ({ productId, proxyId, vectors, }: {
|
|
124
139
|
productId: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { emit, registerEvents } from '@unchainedshop/events';
|
|
2
2
|
import { findPreservingIds, generateDbFilterById, buildSortOptions, mongodb, generateDbObjectId, } from '@unchainedshop/mongodb';
|
|
3
|
-
import { SortDirection } from '@unchainedshop/utils';
|
|
3
|
+
import { executeBulkOperation, SortDirection } from '@unchainedshop/utils';
|
|
4
4
|
import { ProductsCollection, ProductStatus, ProductType, } from "../db/ProductsCollection.js";
|
|
5
5
|
import { configureProductMediaModule } from "./configureProductMediaModule.js";
|
|
6
6
|
import { configureProductPricesModule } from "./configureProductPrices.js";
|
|
@@ -126,6 +126,16 @@ export const configureProductsModule = async (moduleInput) => {
|
|
|
126
126
|
}
|
|
127
127
|
return false;
|
|
128
128
|
};
|
|
129
|
+
const updateProduct = async (productId, doc) => {
|
|
130
|
+
const product = await Products.findOneAndUpdate(generateDbFilterById(productId), {
|
|
131
|
+
$set: {
|
|
132
|
+
updated: new Date(),
|
|
133
|
+
...doc,
|
|
134
|
+
},
|
|
135
|
+
}, { returnDocument: 'after' });
|
|
136
|
+
await emit('PRODUCT_UPDATE', { productId, ...doc, product });
|
|
137
|
+
return productId;
|
|
138
|
+
};
|
|
129
139
|
const proxyProducts = async (product, vectors = [], { includeInactive = false } = {}) => {
|
|
130
140
|
const { proxy } = product;
|
|
131
141
|
let filtered = [...(proxy?.assignments || [])];
|
|
@@ -149,7 +159,7 @@ export const configureProductsModule = async (moduleInput) => {
|
|
|
149
159
|
return {
|
|
150
160
|
findProduct: async (params) => {
|
|
151
161
|
if ('sku' in params) {
|
|
152
|
-
return Products.findOne({ 'warehousing.sku': params.sku }, { sort: { sequence: 1 } });
|
|
162
|
+
return Products.findOne({ 'warehousing.sku': params.sku }, { sort: { sequence: 1, _id: 1 } });
|
|
153
163
|
}
|
|
154
164
|
if ('slug' in params && params.slug != null) {
|
|
155
165
|
return Products.findOne({ slugs: params.slug }, {});
|
|
@@ -260,17 +270,7 @@ export const configureProductsModule = async (moduleInput) => {
|
|
|
260
270
|
await emit('PRODUCT_CREATE', { product });
|
|
261
271
|
return product;
|
|
262
272
|
},
|
|
263
|
-
update:
|
|
264
|
-
const updateDoc = doc;
|
|
265
|
-
const product = await Products.findOneAndUpdate(generateDbFilterById(productId), {
|
|
266
|
-
$set: {
|
|
267
|
-
updated: new Date(),
|
|
268
|
-
...updateDoc,
|
|
269
|
-
},
|
|
270
|
-
}, { returnDocument: 'after' });
|
|
271
|
-
await emit('PRODUCT_UPDATE', { productId, ...updateDoc, product });
|
|
272
|
-
return productId;
|
|
273
|
-
},
|
|
273
|
+
update: updateProduct,
|
|
274
274
|
firstActiveProductProxy: async (productId) => {
|
|
275
275
|
return Products.findOne({ 'proxy.assignments.productId': productId });
|
|
276
276
|
},
|
|
@@ -292,6 +292,31 @@ export const configureProductsModule = async (moduleInput) => {
|
|
|
292
292
|
deleteProductPermanently,
|
|
293
293
|
publish: publishProduct,
|
|
294
294
|
unpublish: unpublishProduct,
|
|
295
|
+
bulkPublish: async (productIds) => executeBulkOperation(productIds, async (productId) => {
|
|
296
|
+
const product = await Products.findOne(generateDbFilterById(productId), {});
|
|
297
|
+
if (!product || !(await publishProduct(product)))
|
|
298
|
+
throw new Error('publish-failed');
|
|
299
|
+
}),
|
|
300
|
+
bulkUnpublish: async (productIds) => executeBulkOperation(productIds, async (productId) => {
|
|
301
|
+
const product = await Products.findOne(generateDbFilterById(productId), {});
|
|
302
|
+
if (!product || !(await unpublishProduct(product)))
|
|
303
|
+
throw new Error('unpublish-failed');
|
|
304
|
+
}),
|
|
305
|
+
bulkUpdateTags: async (productIds, { add = [], remove = [] }) => {
|
|
306
|
+
const tagsToRemove = new Set(remove);
|
|
307
|
+
return executeBulkOperation(productIds, async (productId) => {
|
|
308
|
+
const product = await Products.findOne(generateDbFilterById(productId), {});
|
|
309
|
+
if (!product || (product.status !== ProductStatus.ACTIVE && !isDraftStatus(product.status))) {
|
|
310
|
+
throw new Error('not-found');
|
|
311
|
+
}
|
|
312
|
+
const tags = (product.tags || []).filter((tag) => !tagsToRemove.has(tag));
|
|
313
|
+
for (const tag of add) {
|
|
314
|
+
if (!tags.includes(tag))
|
|
315
|
+
tags.push(tag);
|
|
316
|
+
}
|
|
317
|
+
await updateProduct(productId, { tags });
|
|
318
|
+
});
|
|
319
|
+
},
|
|
295
320
|
assignments: {
|
|
296
321
|
addProxyAssignment: async ({ productId, proxyId, vectors, }) => {
|
|
297
322
|
const assignment = {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/core-products",
|
|
3
3
|
"description": "Product catalog management module for the Unchained Engine",
|
|
4
|
-
"version": "5.0.0-alpha.
|
|
4
|
+
"version": "5.0.0-alpha.5",
|
|
5
5
|
"main": "lib/products-index.js",
|
|
6
6
|
"types": "lib/products-index.d.ts",
|
|
7
7
|
"type": "module",
|
|
@@ -35,13 +35,13 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://github.com/unchainedshop/unchained#readme",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@unchainedshop/events": "^5.0.0-alpha.
|
|
39
|
-
"@unchainedshop/logger": "^5.0.0-alpha.
|
|
40
|
-
"@unchainedshop/mongodb": "^5.0.0-alpha.
|
|
41
|
-
"@unchainedshop/utils": "^5.0.0-alpha.
|
|
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",
|
|
45
|
-
"typescript": "^
|
|
45
|
+
"typescript": "^6.0.3"
|
|
46
46
|
}
|
|
47
47
|
}
|