@unchainedshop/core 4.8.19 → 4.8.20
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.
- package/lib/bulk-importer/handlers/product/create.d.ts +15 -3
- package/lib/bulk-importer/handlers/product/create.js +4 -2
- package/lib/bulk-importer/handlers/product/update.d.ts +15 -3
- package/lib/bulk-importer/handlers/product/update.js +4 -1
- package/lib/directors/FilterDirector.js +23 -18
- package/lib/directors/WorkerDirector.js +1 -1
- package/lib/services/createFilter.d.ts +3 -0
- package/lib/services/createFilter.js +6 -0
- package/lib/services/createFilterOption.d.ts +5 -0
- package/lib/services/createFilterOption.js +8 -0
- package/lib/services/index.d.ts +8 -0
- package/lib/services/index.js +8 -0
- package/lib/services/loadFilterOptions.js +2 -2
- package/lib/services/removeFilterOption.d.ts +6 -0
- package/lib/services/removeFilterOption.js +8 -0
- package/lib/services/updateFilter.d.ts +3 -0
- package/lib/services/updateFilter.js +8 -0
- package/package.json +1 -1
|
@@ -10,7 +10,11 @@ export declare const ProductCreateSpecificationSchema: z.ZodMiniObject<{
|
|
|
10
10
|
readonly TOKENIZED_PRODUCT: "TOKENIZED_PRODUCT";
|
|
11
11
|
}>;
|
|
12
12
|
sequence: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
|
|
13
|
-
status: z.ZodMiniOptional<z.ZodMiniNullable<z.
|
|
13
|
+
status: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniEnum<{
|
|
14
|
+
readonly DRAFT: "DRAFT";
|
|
15
|
+
readonly ACTIVE: "ACTIVE";
|
|
16
|
+
readonly DELETED: "DELETED";
|
|
17
|
+
}>>>;
|
|
14
18
|
published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
|
|
15
19
|
tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
|
|
16
20
|
commerce: z.ZodMiniOptional<z.ZodMiniObject<{
|
|
@@ -67,7 +71,11 @@ export declare const ProductCreatePayloadSchema: z.ZodMiniObject<{
|
|
|
67
71
|
readonly TOKENIZED_PRODUCT: "TOKENIZED_PRODUCT";
|
|
68
72
|
}>;
|
|
69
73
|
sequence: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
|
|
70
|
-
status: z.ZodMiniOptional<z.ZodMiniNullable<z.
|
|
74
|
+
status: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniEnum<{
|
|
75
|
+
readonly DRAFT: "DRAFT";
|
|
76
|
+
readonly ACTIVE: "ACTIVE";
|
|
77
|
+
readonly DELETED: "DELETED";
|
|
78
|
+
}>>>;
|
|
71
79
|
published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
|
|
72
80
|
tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
|
|
73
81
|
commerce: z.ZodMiniOptional<z.ZodMiniObject<{
|
|
@@ -170,7 +178,11 @@ declare namespace createProduct {
|
|
|
170
178
|
readonly TOKENIZED_PRODUCT: "TOKENIZED_PRODUCT";
|
|
171
179
|
}>;
|
|
172
180
|
sequence: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
|
|
173
|
-
status: z.ZodMiniOptional<z.ZodMiniNullable<z.
|
|
181
|
+
status: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniEnum<{
|
|
182
|
+
readonly DRAFT: "DRAFT";
|
|
183
|
+
readonly ACTIVE: "ACTIVE";
|
|
184
|
+
readonly DELETED: "DELETED";
|
|
185
|
+
}>>>;
|
|
174
186
|
published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
|
|
175
187
|
tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
|
|
176
188
|
commerce: z.ZodMiniOptional<z.ZodMiniObject<{
|
|
@@ -3,11 +3,11 @@ import upsertVariations, { ProductVariationSchema } from "./upsertVariations.js"
|
|
|
3
3
|
import upsertMedia from "./upsertMedia.js";
|
|
4
4
|
import { MediaSchema } from "../assortment/upsertMedia.js";
|
|
5
5
|
import convertTagsToLowerCase from "../utils/convertTagsToLowerCase.js";
|
|
6
|
-
import { ProductType } from '@unchainedshop/core-products';
|
|
6
|
+
import { ProductStatus, ProductType } from '@unchainedshop/core-products';
|
|
7
7
|
export const ProductCreateSpecificationSchema = z.object({
|
|
8
8
|
type: z.enum(ProductType),
|
|
9
9
|
sequence: z.optional(z.number()),
|
|
10
|
-
status: z.nullish(z.
|
|
10
|
+
status: z.nullish(z.enum(ProductStatus)),
|
|
11
11
|
published: z.nullish(z.iso.datetime()),
|
|
12
12
|
tags: z.optional(z.array(z.string())),
|
|
13
13
|
commerce: z.optional(z.object({
|
|
@@ -59,6 +59,7 @@ export const ProductCreatePayloadSchema = z.object({
|
|
|
59
59
|
media: z.optional(z.array(MediaSchema)),
|
|
60
60
|
variations: z.optional(z.array(ProductVariationSchema)),
|
|
61
61
|
});
|
|
62
|
+
const normalizeStatus = (status) => (status === ProductStatus.DRAFT ? null : status);
|
|
62
63
|
const transformSpecification = (specification) => {
|
|
63
64
|
const { variationResolvers: assignments, content, supply, warehousing, sequence, ...productData } = specification;
|
|
64
65
|
const tags = productData?.tags ? convertTagsToLowerCase(productData.tags) : [];
|
|
@@ -66,6 +67,7 @@ const transformSpecification = (specification) => {
|
|
|
66
67
|
return {
|
|
67
68
|
...productData,
|
|
68
69
|
published: productData.published ? new Date(productData.published) : undefined,
|
|
70
|
+
...(productData.status !== undefined && { status: normalizeStatus(productData.status) }),
|
|
69
71
|
tags,
|
|
70
72
|
warehousing,
|
|
71
73
|
supply,
|
|
@@ -4,7 +4,11 @@ import type { Services } from '../../../services/index.ts';
|
|
|
4
4
|
export declare const ProductUpdateSpecificationSchema: z.ZodMiniObject<{
|
|
5
5
|
type: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
6
6
|
sequence: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
|
|
7
|
-
status: z.ZodMiniOptional<z.ZodMiniNullable<z.
|
|
7
|
+
status: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniEnum<{
|
|
8
|
+
readonly DRAFT: "DRAFT";
|
|
9
|
+
readonly ACTIVE: "ACTIVE";
|
|
10
|
+
readonly DELETED: "DELETED";
|
|
11
|
+
}>>>;
|
|
8
12
|
published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
|
|
9
13
|
tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
|
|
10
14
|
commerce: z.ZodMiniOptional<z.ZodMiniObject<{
|
|
@@ -55,7 +59,11 @@ export declare const ProductUpdatePayloadSchema: z.ZodMiniObject<{
|
|
|
55
59
|
specification: z.ZodMiniOptional<z.ZodMiniObject<{
|
|
56
60
|
type: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
57
61
|
sequence: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
|
|
58
|
-
status: z.ZodMiniOptional<z.ZodMiniNullable<z.
|
|
62
|
+
status: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniEnum<{
|
|
63
|
+
readonly DRAFT: "DRAFT";
|
|
64
|
+
readonly ACTIVE: "ACTIVE";
|
|
65
|
+
readonly DELETED: "DELETED";
|
|
66
|
+
}>>>;
|
|
59
67
|
published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
|
|
60
68
|
tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
|
|
61
69
|
commerce: z.ZodMiniOptional<z.ZodMiniObject<{
|
|
@@ -152,7 +160,11 @@ declare namespace updateProduct {
|
|
|
152
160
|
specification: z.ZodMiniOptional<z.ZodMiniObject<{
|
|
153
161
|
type: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
154
162
|
sequence: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
|
|
155
|
-
status: z.ZodMiniOptional<z.ZodMiniNullable<z.
|
|
163
|
+
status: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniEnum<{
|
|
164
|
+
readonly DRAFT: "DRAFT";
|
|
165
|
+
readonly ACTIVE: "ACTIVE";
|
|
166
|
+
readonly DELETED: "DELETED";
|
|
167
|
+
}>>>;
|
|
156
168
|
published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
|
|
157
169
|
tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
|
|
158
170
|
commerce: z.ZodMiniOptional<z.ZodMiniObject<{
|
|
@@ -3,10 +3,11 @@ import upsertVariations, { ProductVariationSchema } from "./upsertVariations.js"
|
|
|
3
3
|
import upsertMedia, { MediaSchema } from "./upsertMedia.js";
|
|
4
4
|
import createProduct, { ProductCreatePayloadSchema } from "./create.js";
|
|
5
5
|
import convertTagsToLowerCase from "../utils/convertTagsToLowerCase.js";
|
|
6
|
+
import { ProductStatus } from '@unchainedshop/core-products';
|
|
6
7
|
export const ProductUpdateSpecificationSchema = z.object({
|
|
7
8
|
type: z.optional(z.string()),
|
|
8
9
|
sequence: z.optional(z.number()),
|
|
9
|
-
status: z.nullish(z.
|
|
10
|
+
status: z.nullish(z.enum(ProductStatus)),
|
|
10
11
|
published: z.nullish(z.iso.datetime()),
|
|
11
12
|
tags: z.optional(z.array(z.string())),
|
|
12
13
|
commerce: z.optional(z.object({
|
|
@@ -58,6 +59,7 @@ export const ProductUpdatePayloadSchema = z.object({
|
|
|
58
59
|
media: z.optional(z.array(MediaSchema)),
|
|
59
60
|
variations: z.optional(z.array(ProductVariationSchema)),
|
|
60
61
|
});
|
|
62
|
+
const normalizeStatus = (status) => (status === ProductStatus.DRAFT ? null : status);
|
|
61
63
|
const transformSpecification = (specification) => {
|
|
62
64
|
const { variationResolvers: assignments, content, supply, warehousing, ...productData } = specification;
|
|
63
65
|
const tags = productData?.tags ? convertTagsToLowerCase(productData.tags) : [];
|
|
@@ -65,6 +67,7 @@ const transformSpecification = (specification) => {
|
|
|
65
67
|
return {
|
|
66
68
|
...productData,
|
|
67
69
|
published: productData.published ? new Date(productData.published) : undefined,
|
|
70
|
+
...(productData.status !== undefined && { status: normalizeStatus(productData.status) }),
|
|
68
71
|
tags,
|
|
69
72
|
warehousing,
|
|
70
73
|
supply,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mongodb } from '@unchainedshop/mongodb';
|
|
2
2
|
import { BaseDirector } from '@unchainedshop/utils';
|
|
3
|
-
import { filtersSettings, FilterType, } from '@unchainedshop/core-filters';
|
|
3
|
+
import { filterCacheGeneration, filtersSettings, FilterType, } from '@unchainedshop/core-filters';
|
|
4
4
|
export const parseQueryArray = (query) => (query || []).reduce((accumulator, { key, value }) => ({
|
|
5
5
|
...accumulator,
|
|
6
6
|
[key]: accumulator[key] ? accumulator[key].concat(value) : [value],
|
|
@@ -70,18 +70,19 @@ export const FilterDirector = {
|
|
|
70
70
|
},
|
|
71
71
|
async buildProductIdMap(filter, unchainedAPI) {
|
|
72
72
|
const allProductIds = await this.findProductIds(filter, {}, unchainedAPI);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
73
|
+
if (filter.type === FilterType.SWITCH) {
|
|
74
|
+
return [
|
|
75
|
+
allProductIds,
|
|
76
|
+
{
|
|
77
|
+
true: await this.findProductIds(filter, { value: true }, unchainedAPI),
|
|
78
|
+
false: await this.findProductIds(filter, { value: { $in: [null, false] } }, unchainedAPI),
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
const productIdsMap = Object.create(null);
|
|
83
|
+
for (const option of filter.options || []) {
|
|
84
|
+
productIdsMap[option] = await this.findProductIds(filter, { value: option }, unchainedAPI);
|
|
85
|
+
}
|
|
85
86
|
return [allProductIds, productIdsMap];
|
|
86
87
|
},
|
|
87
88
|
async filterProductIds(filter, { values, forceLiveCollection }, unchainedAPI) {
|
|
@@ -92,11 +93,13 @@ export const FilterDirector = {
|
|
|
92
93
|
return new Set(allProductIds);
|
|
93
94
|
const result = new Set();
|
|
94
95
|
for (const key of filteredKeys) {
|
|
96
|
+
if (!Object.hasOwn(keyToProductIdMap, key))
|
|
97
|
+
continue;
|
|
95
98
|
const additionalValues = keyToProductIdMap[key];
|
|
96
|
-
if (additionalValues)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
if (!additionalValues)
|
|
100
|
+
continue;
|
|
101
|
+
for (const val of additionalValues)
|
|
102
|
+
result.add(val);
|
|
100
103
|
}
|
|
101
104
|
return result;
|
|
102
105
|
},
|
|
@@ -165,6 +168,8 @@ export const FilterDirector = {
|
|
|
165
168
|
if (!filter)
|
|
166
169
|
return;
|
|
167
170
|
const [productIds, productIdMap] = await this.buildProductIdMap(filter, unchainedAPI);
|
|
168
|
-
await
|
|
171
|
+
if (!(await unchainedAPI.modules.filters.filterExists({ filterId: filter._id })))
|
|
172
|
+
return;
|
|
173
|
+
await filtersSettings.setCachedProductIds(filter._id, productIds, productIdMap, filterCacheGeneration(filter));
|
|
169
174
|
},
|
|
170
175
|
};
|
|
@@ -54,7 +54,7 @@ export const WorkerDirector = {
|
|
|
54
54
|
logger.warn(`WorkerDirector: No registered adapter for type: ${type}`);
|
|
55
55
|
}
|
|
56
56
|
try {
|
|
57
|
-
const output = await adapter.doWork(input, unchainedAPI, workId);
|
|
57
|
+
const output = await adapter.doWork(input ?? {}, unchainedAPI, workId);
|
|
58
58
|
return output;
|
|
59
59
|
}
|
|
60
60
|
catch (error) {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FilterDirector } from "../core-index.js";
|
|
2
|
+
export async function createFilterOptionService(filterId, { value }) {
|
|
3
|
+
const filter = await this.filters.createFilterOption(filterId, { value });
|
|
4
|
+
if (filter) {
|
|
5
|
+
await FilterDirector.invalidateProductIdCache(filter, { modules: this });
|
|
6
|
+
}
|
|
7
|
+
return filter;
|
|
8
|
+
}
|
package/lib/services/index.d.ts
CHANGED
|
@@ -41,6 +41,10 @@ import { verifyQuotationService } from './verifyQuotation.ts';
|
|
|
41
41
|
import { loadFiltersService } from './loadFilters.ts';
|
|
42
42
|
import { loadFilterOptionsService } from './loadFilterOptions.ts';
|
|
43
43
|
import { removeFilterService } from './removeFilter.ts';
|
|
44
|
+
import { createFilterService } from './createFilter.ts';
|
|
45
|
+
import { updateFilterService } from './updateFilter.ts';
|
|
46
|
+
import { createFilterOptionService } from './createFilterOption.ts';
|
|
47
|
+
import { removeFilterOptionService } from './removeFilterOption.ts';
|
|
44
48
|
import { removeCartDiscountService } from './removeCartDiscount.ts';
|
|
45
49
|
import { addMultipleCartProductsService } from './addMultipleCartProducts.ts';
|
|
46
50
|
import { ercMetadataService } from './ercMetadata.ts';
|
|
@@ -131,6 +135,10 @@ export default function initServices(modules: Modules, customServices?: CustomSe
|
|
|
131
135
|
loadFilters: Bound<typeof loadFiltersService>;
|
|
132
136
|
loadFilterOptions: Bound<typeof loadFilterOptionsService>;
|
|
133
137
|
removeFilter: Bound<typeof removeFilterService>;
|
|
138
|
+
createFilter: Bound<typeof createFilterService>;
|
|
139
|
+
updateFilter: Bound<typeof updateFilterService>;
|
|
140
|
+
createFilterOption: Bound<typeof createFilterOptionService>;
|
|
141
|
+
removeFilterOption: Bound<typeof removeFilterOptionService>;
|
|
134
142
|
};
|
|
135
143
|
warehousing: {
|
|
136
144
|
ercMetadata: Bound<typeof ercMetadataService>;
|
package/lib/services/index.js
CHANGED
|
@@ -40,6 +40,10 @@ import { verifyQuotationService } from "./verifyQuotation.js";
|
|
|
40
40
|
import { loadFiltersService } from "./loadFilters.js";
|
|
41
41
|
import { loadFilterOptionsService } from "./loadFilterOptions.js";
|
|
42
42
|
import { removeFilterService } from "./removeFilter.js";
|
|
43
|
+
import { createFilterService } from "./createFilter.js";
|
|
44
|
+
import { updateFilterService } from "./updateFilter.js";
|
|
45
|
+
import { createFilterOptionService } from "./createFilterOption.js";
|
|
46
|
+
import { removeFilterOptionService } from "./removeFilterOption.js";
|
|
43
47
|
import { removeCartDiscountService } from "./removeCartDiscount.js";
|
|
44
48
|
import { addMultipleCartProductsService } from "./addMultipleCartProducts.js";
|
|
45
49
|
import { ercMetadataService } from "./ercMetadata.js";
|
|
@@ -142,6 +146,10 @@ export default function initServices(modules, customServices = {}) {
|
|
|
142
146
|
loadFilters: loadFiltersService,
|
|
143
147
|
loadFilterOptions: loadFilterOptionsService,
|
|
144
148
|
removeFilter: removeFilterService,
|
|
149
|
+
createFilter: createFilterService,
|
|
150
|
+
updateFilter: updateFilterService,
|
|
151
|
+
createFilterOption: createFilterOptionService,
|
|
152
|
+
removeFilterOption: removeFilterOptionService,
|
|
145
153
|
},
|
|
146
154
|
warehousing: {
|
|
147
155
|
ercMetadata: ercMetadataService,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { filterOptionValues } from '@unchainedshop/core-filters';
|
|
2
2
|
import { FilterDirector, parseQueryArray } from "../directors/FilterDirector.js";
|
|
3
3
|
export async function loadFilterOptionsService(filter, params) {
|
|
4
4
|
const { forceLiveCollection, productIdSet, searchQuery } = params;
|
|
5
5
|
const filterQueryParsed = parseQueryArray(searchQuery?.filterQuery);
|
|
6
6
|
const values = filterQueryParsed[filter.key];
|
|
7
|
-
const allOptions = (filter
|
|
7
|
+
const allOptions = filterOptionValues(filter);
|
|
8
8
|
const mappedOptions = await Promise.all(allOptions.map(async (value) => {
|
|
9
9
|
const filterOptionProductIds = await FilterDirector.filterProductIds(filter, {
|
|
10
10
|
values: [value],
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Filter } from '@unchainedshop/core-filters';
|
|
2
|
+
import type { Modules } from '../modules.ts';
|
|
3
|
+
export declare function removeFilterOptionService(this: Modules, { filterId, filterOptionValue }: {
|
|
4
|
+
filterId: string;
|
|
5
|
+
filterOptionValue: string;
|
|
6
|
+
}): Promise<Filter | null>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FilterDirector } from "../core-index.js";
|
|
2
|
+
export async function removeFilterOptionService({ filterId, filterOptionValue }) {
|
|
3
|
+
const filter = await this.filters.removeFilterOption({ filterId, filterOptionValue });
|
|
4
|
+
if (filter) {
|
|
5
|
+
await FilterDirector.invalidateProductIdCache(filter, { modules: this });
|
|
6
|
+
}
|
|
7
|
+
return filter;
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FilterDirector } from "../core-index.js";
|
|
2
|
+
export async function updateFilterService(filterId, doc) {
|
|
3
|
+
const updatedFilter = await this.filters.update(filterId, doc);
|
|
4
|
+
if (updatedFilter) {
|
|
5
|
+
await FilterDirector.invalidateProductIdCache(updatedFilter, { modules: this });
|
|
6
|
+
}
|
|
7
|
+
return updatedFilter;
|
|
8
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/core",
|
|
3
3
|
"description": "Core orchestration package for the Unchained Engine with business services and directors",
|
|
4
|
-
"version": "4.8.
|
|
4
|
+
"version": "4.8.20",
|
|
5
5
|
"main": "lib/core-index.js",
|
|
6
6
|
"types": "lib/core-index.d.ts",
|
|
7
7
|
"type": "module",
|