@unchainedshop/core 4.4.0 → 4.5.0
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/core-index.d.ts +1 -0
- package/lib/core-index.js +1 -0
- package/lib/directors/BaseWorker.js +2 -2
- package/lib/directors/DeliveryPricingAdapter.d.ts +1 -1
- package/lib/directors/DeliveryPricingDirector.d.ts +1 -1
- package/lib/directors/IntervalWorker.d.ts +2 -2
- package/lib/directors/IntervalWorker.js +4 -4
- package/lib/directors/PaymentPricingAdapter.d.ts +2 -2
- package/lib/directors/PaymentPricingAdapter.js +1 -1
- package/lib/directors/PaymentPricingDirector.d.ts +1 -1
- package/lib/directors/WorkerDirector.d.ts +1 -1
- package/lib/services/addMultipleCartProducts.d.ts +18 -0
- package/lib/services/addMultipleCartProducts.js +25 -0
- package/lib/services/createFileDownloadURL.d.ts +7 -0
- package/lib/services/createFileDownloadURL.js +10 -0
- package/lib/services/findProductSiblings.d.ts +9 -0
- package/lib/services/findProductSiblings.js +18 -0
- package/lib/services/index.d.ts +26 -0
- package/lib/services/index.js +26 -0
- package/lib/services/isTokenInvalidateable.d.ts +5 -0
- package/lib/services/isTokenInvalidateable.js +15 -0
- package/lib/services/removeCartDiscount.d.ts +10 -0
- package/lib/services/removeCartDiscount.js +14 -0
- package/lib/services/removeFiles.js +1 -1
- package/lib/services/removeFilter.d.ts +5 -0
- package/lib/services/removeFilter.js +5 -0
- package/lib/services/resolveOrderItemDispatches.d.ts +19 -0
- package/lib/services/resolveOrderItemDispatches.js +38 -0
- package/lib/services/resolveTokenStatus.d.ts +5 -0
- package/lib/services/resolveTokenStatus.js +15 -0
- package/lib/services/simulateConfigurablePriceRange.d.ts +13 -0
- package/lib/services/simulateConfigurablePriceRange.js +39 -0
- package/lib/services/simulateDeliveryPricing.d.ts +21 -0
- package/lib/services/simulateDeliveryPricing.js +23 -0
- package/lib/services/simulatePaymentPricing.d.ts +21 -0
- package/lib/services/simulatePaymentPricing.js +23 -0
- package/lib/services/updateUserAvatarAfterUpload.js +2 -2
- package/lib/utils/schedule.d.ts +22 -0
- package/lib/utils/schedule.js +148 -0
- package/package.json +21 -22
package/lib/core-index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './bulk-importer/index.ts';
|
|
|
7
7
|
export * from './services/index.ts';
|
|
8
8
|
export * from './directors/index.ts';
|
|
9
9
|
export * from './factory/index.ts';
|
|
10
|
+
export { default as schedule, type ScheduleData } from './utils/schedule.ts';
|
|
10
11
|
export interface UnchainedCoreOptions {
|
|
11
12
|
db: mongodb.Db;
|
|
12
13
|
migrationRepository: MigrationRepository<UnchainedCore>;
|
package/lib/core-index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./bulk-importer/index.js";
|
|
|
7
7
|
export * from "./services/index.js";
|
|
8
8
|
export * from "./directors/index.js";
|
|
9
9
|
export * from "./factory/index.js";
|
|
10
|
+
export { default as schedule } from "./utils/schedule.js";
|
|
10
11
|
export const initCore = async ({ db, migrationRepository, bulkImporter: bulkImporterOptions = {}, modules: customModules = {}, services: customServices = {}, options = {}, }) => {
|
|
11
12
|
const bulkImporter = createBulkImporterFactory(db, bulkImporterOptions);
|
|
12
13
|
const modules = await initModules({ db, migrationRepository, options }, customModules);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import schedule from "../utils/schedule.js";
|
|
2
2
|
import { WorkerDirector } from "./WorkerDirector.js";
|
|
3
3
|
export const BaseWorker = {
|
|
4
4
|
key: 'shop.unchained.worker.base',
|
|
@@ -37,7 +37,7 @@ export const BaseWorker = {
|
|
|
37
37
|
}
|
|
38
38
|
const fixedSchedule = { ...workConfig.schedule };
|
|
39
39
|
fixedSchedule.schedules[0].s = [0];
|
|
40
|
-
const nextDate =
|
|
40
|
+
const nextDate = schedule.schedule(fixedSchedule).next(1, referenceDate);
|
|
41
41
|
nextDate.setMilliseconds(0);
|
|
42
42
|
const workData = {
|
|
43
43
|
type: workConfig.type,
|
|
@@ -37,7 +37,7 @@ export interface DeliveryPricingAdapterContext extends BasePricingAdapterContext
|
|
|
37
37
|
currencyCode?: string;
|
|
38
38
|
provider: DeliveryProvider;
|
|
39
39
|
providerContext?: any;
|
|
40
|
-
order
|
|
40
|
+
order?: Order;
|
|
41
41
|
orderDelivery?: OrderDelivery;
|
|
42
42
|
user: User;
|
|
43
43
|
discounts: OrderDiscount[];
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type ScheduleData } from '
|
|
1
|
+
import { type ScheduleData } from '../utils/schedule.ts';
|
|
2
2
|
import { type IWorker } from './BaseWorker.ts';
|
|
3
3
|
export interface IntervalWorkerParams {
|
|
4
4
|
workerId?: string;
|
|
5
5
|
batchCount?: number;
|
|
6
6
|
schedule?: ScheduleData;
|
|
7
7
|
}
|
|
8
|
-
export declare const scheduleToInterval: (
|
|
8
|
+
export declare const scheduleToInterval: (scheduleData: ScheduleData) => number;
|
|
9
9
|
export declare const IntervalWorker: IWorker<IntervalWorkerParams>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import schedule, {} from "../utils/schedule.js";
|
|
2
2
|
import { BaseWorker } from "./BaseWorker.js";
|
|
3
3
|
import { createLogger } from '@unchainedshop/logger';
|
|
4
4
|
const { NODE_ENV } = process.env;
|
|
5
5
|
const logger = createLogger('unchained:worker:interval');
|
|
6
|
-
const defaultSchedule =
|
|
7
|
-
export const scheduleToInterval = (
|
|
6
|
+
const defaultSchedule = schedule.parse.text(NODE_ENV !== 'production' ? 'every 2 seconds' : 'every 30 seconds');
|
|
7
|
+
export const scheduleToInterval = (scheduleData) => {
|
|
8
8
|
const referenceDate = new Date(1000);
|
|
9
|
-
const nextDates =
|
|
9
|
+
const nextDates = schedule.schedule(scheduleData).next(2, referenceDate);
|
|
10
10
|
if (!nextDates || nextDates.length < 2) {
|
|
11
11
|
throw new Error('Schedule must produce at least 2 consecutive dates');
|
|
12
12
|
}
|
|
@@ -12,10 +12,10 @@ export interface PaymentPricingCalculation extends PricingCalculation {
|
|
|
12
12
|
}
|
|
13
13
|
export interface PaymentPricingAdapterContext extends BasePricingAdapterContext {
|
|
14
14
|
countryCode?: string;
|
|
15
|
-
|
|
15
|
+
currencyCode?: string;
|
|
16
16
|
user: User | null;
|
|
17
17
|
orderPayment?: OrderPayment;
|
|
18
|
-
order
|
|
18
|
+
order?: Order;
|
|
19
19
|
provider: PaymentProvider;
|
|
20
20
|
discounts: OrderDiscount[];
|
|
21
21
|
}
|
|
@@ -8,7 +8,7 @@ export const PaymentPricingAdapter = {
|
|
|
8
8
|
},
|
|
9
9
|
actions: (params) => {
|
|
10
10
|
const { context } = params;
|
|
11
|
-
const
|
|
11
|
+
const currencyCode = context.currencyCode || context.order?.currencyCode;
|
|
12
12
|
const baseActions = basePricingAdapter.actions(params);
|
|
13
13
|
const resultSheet = PaymentPricingSheet({ currencyCode });
|
|
14
14
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Work, WorkData, WorkResult } from '@unchainedshop/core-worker';
|
|
2
2
|
import { type IBaseDirector } from '@unchainedshop/utils';
|
|
3
|
-
import type { ScheduleData } from '
|
|
3
|
+
import type { ScheduleData } from '../utils/schedule.ts';
|
|
4
4
|
import type { IWorkerAdapter } from './WorkerAdapter.ts';
|
|
5
5
|
import type { Modules } from '../modules.ts';
|
|
6
6
|
export type WorkScheduleConfiguration = Pick<WorkData, 'timeout' | 'retries' | 'priority' | 'worker' | 'scheduleId'> & {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Modules } from '../modules.ts';
|
|
2
|
+
import type { Order } from '@unchainedshop/core-orders';
|
|
3
|
+
export declare function addMultipleCartProductsService(this: Modules, { orderId, items, context, }: {
|
|
4
|
+
orderId: string;
|
|
5
|
+
items: {
|
|
6
|
+
productId: string;
|
|
7
|
+
quantity: number;
|
|
8
|
+
configuration?: {
|
|
9
|
+
key: string;
|
|
10
|
+
value: string;
|
|
11
|
+
}[];
|
|
12
|
+
}[];
|
|
13
|
+
context: {
|
|
14
|
+
localeContext: Intl.Locale;
|
|
15
|
+
userId?: string;
|
|
16
|
+
countryCode?: string;
|
|
17
|
+
};
|
|
18
|
+
}): Promise<Order | null>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ordersSettings } from '@unchainedshop/core-orders';
|
|
2
|
+
export async function addMultipleCartProductsService({ orderId, items, context, }) {
|
|
3
|
+
const order = await this.orders.findOrder({ orderId });
|
|
4
|
+
if (!order)
|
|
5
|
+
return null;
|
|
6
|
+
for (const { productId, quantity, configuration } of items) {
|
|
7
|
+
const originalProduct = await this.products.findProduct({ productId });
|
|
8
|
+
if (!originalProduct) {
|
|
9
|
+
throw new Error(`Product not found: ${productId}`);
|
|
10
|
+
}
|
|
11
|
+
if (quantity < 1) {
|
|
12
|
+
throw new Error(`Invalid quantity for product: ${productId}`);
|
|
13
|
+
}
|
|
14
|
+
const product = await this.products.resolveOrderableProduct(originalProduct, { configuration });
|
|
15
|
+
await ordersSettings.validateOrderPosition({ order, product, configuration, quantityDiff: quantity }, { modules: this, ...context });
|
|
16
|
+
await this.orders.positions.addProductItem({
|
|
17
|
+
quantity,
|
|
18
|
+
configuration,
|
|
19
|
+
originalProductId: originalProduct._id,
|
|
20
|
+
productId: product._id,
|
|
21
|
+
orderId: order._id,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return order;
|
|
25
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type File } from '@unchainedshop/core-files';
|
|
2
|
+
import type { Modules } from '../modules.ts';
|
|
3
|
+
export declare function createFileDownloadURLService(this: Modules, { file, expires, params, }: {
|
|
4
|
+
file: File;
|
|
5
|
+
expires?: number;
|
|
6
|
+
params?: Record<string, any>;
|
|
7
|
+
}): Promise<string | null>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getFileAdapter } from '@unchainedshop/core-files';
|
|
2
|
+
export async function createFileDownloadURLService({ file, expires, params = {}, }) {
|
|
3
|
+
if (!file)
|
|
4
|
+
return null;
|
|
5
|
+
const fileUploadAdapter = getFileAdapter();
|
|
6
|
+
const url = await fileUploadAdapter.createDownloadURL(file, expires);
|
|
7
|
+
if (!url)
|
|
8
|
+
return null;
|
|
9
|
+
return this.files.normalizeUrl(url, params);
|
|
10
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Product } from '@unchainedshop/core-products';
|
|
2
|
+
import type { Modules } from '../modules.ts';
|
|
3
|
+
export declare function findProductSiblingsService(this: Modules, { product, assortmentId, limit, offset, includeInactive, }: {
|
|
4
|
+
product: Product;
|
|
5
|
+
assortmentId?: string;
|
|
6
|
+
limit?: number;
|
|
7
|
+
offset?: number;
|
|
8
|
+
includeInactive?: boolean;
|
|
9
|
+
}): Promise<Product[]>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export async function findProductSiblingsService({ product, assortmentId, limit, offset, includeInactive = false, }) {
|
|
2
|
+
const productId = product._id;
|
|
3
|
+
const assortmentIds = assortmentId
|
|
4
|
+
? [assortmentId]
|
|
5
|
+
: await this.assortments.products.findAssortmentIds({ productId });
|
|
6
|
+
if (!assortmentIds.length)
|
|
7
|
+
return [];
|
|
8
|
+
const productIds = await this.assortments.products.findSiblings({
|
|
9
|
+
productId,
|
|
10
|
+
assortmentIds,
|
|
11
|
+
});
|
|
12
|
+
return this.products.findProducts({
|
|
13
|
+
productIds,
|
|
14
|
+
includeDrafts: includeInactive,
|
|
15
|
+
limit,
|
|
16
|
+
offset,
|
|
17
|
+
});
|
|
18
|
+
}
|
package/lib/services/index.d.ts
CHANGED
|
@@ -39,13 +39,24 @@ import { rejectQuotationService } from './rejectQuotation.ts';
|
|
|
39
39
|
import { verifyQuotationService } from './verifyQuotation.ts';
|
|
40
40
|
import { loadFiltersService } from './loadFilters.ts';
|
|
41
41
|
import { loadFilterOptionsService } from './loadFilterOptions.ts';
|
|
42
|
+
import { removeFilterService } from './removeFilter.ts';
|
|
43
|
+
import { removeCartDiscountService } from './removeCartDiscount.ts';
|
|
44
|
+
import { addMultipleCartProductsService } from './addMultipleCartProducts.ts';
|
|
42
45
|
import { ercMetadataService } from './ercMetadata.ts';
|
|
43
46
|
import { simulateProductPricingService } from './simulateProductPricing.ts';
|
|
44
47
|
import { simulateProductDispatchingService } from './simulateProductDispatching.ts';
|
|
45
48
|
import { simulateProductInventoryService } from './simulateProductInventory.ts';
|
|
49
|
+
import { simulateDeliveryPricingService } from './simulateDeliveryPricing.ts';
|
|
50
|
+
import { simulatePaymentPricingService } from './simulatePaymentPricing.ts';
|
|
46
51
|
import { findOrInitCartService } from './findOrInitCart.ts';
|
|
47
52
|
import { addMessageService } from './addMessage.ts';
|
|
48
53
|
import { generateOrderFromEnrollmentService } from './generateOrderFromEnrollment.ts';
|
|
54
|
+
import { resolveOrderItemDispatchesService } from './resolveOrderItemDispatches.ts';
|
|
55
|
+
import { findProductSiblingsService } from './findProductSiblings.ts';
|
|
56
|
+
import { simulateConfigurablePriceRangeService } from './simulateConfigurablePriceRange.ts';
|
|
57
|
+
import { createFileDownloadURLService } from './createFileDownloadURL.ts';
|
|
58
|
+
import { resolveTokenStatusService } from './resolveTokenStatus.ts';
|
|
59
|
+
import { isTokenInvalidateableService } from './isTokenInvalidateable.ts';
|
|
49
60
|
export type ServiceInterface = (this: Modules, ...args: any[]) => Promise<any> | any;
|
|
50
61
|
export type Bound<T extends ServiceInterface> = OmitThisParameter<T>;
|
|
51
62
|
export type CustomServices = Record<string, ServiceInterface | Record<string, ServiceInterface>>;
|
|
@@ -60,6 +71,7 @@ export default function initServices(modules: Modules, customServices?: CustomSe
|
|
|
60
71
|
uploadFileFromStream: Bound<typeof uploadFileFromStreamService>;
|
|
61
72
|
removeFiles: Bound<typeof removeFilesService>;
|
|
62
73
|
createDownloadStream: Bound<typeof createDownloadStreamService>;
|
|
74
|
+
createFileDownloadURL: Bound<typeof createFileDownloadURLService>;
|
|
63
75
|
};
|
|
64
76
|
orders: {
|
|
65
77
|
registerPaymentCredentials: Bound<typeof registerPaymentCredentialsService>;
|
|
@@ -78,12 +90,17 @@ export default function initServices(modules: Modules, customServices?: CustomSe
|
|
|
78
90
|
rejectOrder: Bound<typeof rejectOrderService>;
|
|
79
91
|
discountedEntities: Bound<typeof discountedEntitiesService>;
|
|
80
92
|
createManualOrderDiscount: Bound<typeof createManualOrderDiscountService>;
|
|
93
|
+
resolveOrderItemDispatches: Bound<typeof resolveOrderItemDispatchesService>;
|
|
94
|
+
removeCartDiscount: Bound<typeof removeCartDiscountService>;
|
|
95
|
+
addMultipleCartProducts: Bound<typeof addMultipleCartProductsService>;
|
|
81
96
|
};
|
|
82
97
|
products: {
|
|
83
98
|
simulateProductPricing: Bound<typeof simulateProductPricingService>;
|
|
84
99
|
simulateProductDispatching: Bound<typeof simulateProductDispatchingService>;
|
|
85
100
|
simulateProductInventory: Bound<typeof simulateProductInventoryService>;
|
|
86
101
|
removeProduct: Bound<typeof removeProductService>;
|
|
102
|
+
findProductSiblings: Bound<typeof findProductSiblingsService>;
|
|
103
|
+
simulateConfigurablePriceRange: Bound<typeof simulateConfigurablePriceRangeService>;
|
|
87
104
|
};
|
|
88
105
|
users: {
|
|
89
106
|
migrateUserData: Bound<typeof migrateUserDataService>;
|
|
@@ -111,12 +128,21 @@ export default function initServices(modules: Modules, customServices?: CustomSe
|
|
|
111
128
|
invalidateFilterCache: Bound<typeof invalidateFilterCacheService>;
|
|
112
129
|
loadFilters: Bound<typeof loadFiltersService>;
|
|
113
130
|
loadFilterOptions: Bound<typeof loadFilterOptionsService>;
|
|
131
|
+
removeFilter: Bound<typeof removeFilterService>;
|
|
114
132
|
};
|
|
115
133
|
warehousing: {
|
|
116
134
|
ercMetadata: Bound<typeof ercMetadataService>;
|
|
135
|
+
resolveTokenStatus: Bound<typeof resolveTokenStatusService>;
|
|
136
|
+
isTokenInvalidateable: Bound<typeof isTokenInvalidateableService>;
|
|
117
137
|
};
|
|
118
138
|
worker: {
|
|
119
139
|
addMessage: Bound<typeof addMessageService>;
|
|
120
140
|
};
|
|
141
|
+
delivery: {
|
|
142
|
+
simulateDeliveryPricing: Bound<typeof simulateDeliveryPricingService>;
|
|
143
|
+
};
|
|
144
|
+
payment: {
|
|
145
|
+
simulatePaymentPricing: Bound<typeof simulatePaymentPricingService>;
|
|
146
|
+
};
|
|
121
147
|
};
|
|
122
148
|
export type Services = ReturnType<typeof initServices>;
|
package/lib/services/index.js
CHANGED
|
@@ -38,13 +38,24 @@ import { rejectQuotationService } from "./rejectQuotation.js";
|
|
|
38
38
|
import { verifyQuotationService } from "./verifyQuotation.js";
|
|
39
39
|
import { loadFiltersService } from "./loadFilters.js";
|
|
40
40
|
import { loadFilterOptionsService } from "./loadFilterOptions.js";
|
|
41
|
+
import { removeFilterService } from "./removeFilter.js";
|
|
42
|
+
import { removeCartDiscountService } from "./removeCartDiscount.js";
|
|
43
|
+
import { addMultipleCartProductsService } from "./addMultipleCartProducts.js";
|
|
41
44
|
import { ercMetadataService } from "./ercMetadata.js";
|
|
42
45
|
import { simulateProductPricingService } from "./simulateProductPricing.js";
|
|
43
46
|
import { simulateProductDispatchingService } from "./simulateProductDispatching.js";
|
|
44
47
|
import { simulateProductInventoryService } from "./simulateProductInventory.js";
|
|
48
|
+
import { simulateDeliveryPricingService } from "./simulateDeliveryPricing.js";
|
|
49
|
+
import { simulatePaymentPricingService } from "./simulatePaymentPricing.js";
|
|
45
50
|
import { findOrInitCartService } from "./findOrInitCart.js";
|
|
46
51
|
import { addMessageService } from "./addMessage.js";
|
|
47
52
|
import { generateOrderFromEnrollmentService } from "./generateOrderFromEnrollment.js";
|
|
53
|
+
import { resolveOrderItemDispatchesService } from "./resolveOrderItemDispatches.js";
|
|
54
|
+
import { findProductSiblingsService } from "./findProductSiblings.js";
|
|
55
|
+
import { simulateConfigurablePriceRangeService } from "./simulateConfigurablePriceRange.js";
|
|
56
|
+
import { createFileDownloadURLService } from "./createFileDownloadURL.js";
|
|
57
|
+
import { resolveTokenStatusService } from "./resolveTokenStatus.js";
|
|
58
|
+
import { isTokenInvalidateableService } from "./isTokenInvalidateable.js";
|
|
48
59
|
function bindMethodsToModules(modules) {
|
|
49
60
|
return {
|
|
50
61
|
get(target, prop, receiver) {
|
|
@@ -71,6 +82,7 @@ export default function initServices(modules, customServices = {}) {
|
|
|
71
82
|
uploadFileFromStream: uploadFileFromStreamService,
|
|
72
83
|
removeFiles: removeFilesService,
|
|
73
84
|
createDownloadStream: createDownloadStreamService,
|
|
85
|
+
createFileDownloadURL: createFileDownloadURLService,
|
|
74
86
|
},
|
|
75
87
|
orders: {
|
|
76
88
|
registerPaymentCredentials: registerPaymentCredentialsService,
|
|
@@ -89,12 +101,17 @@ export default function initServices(modules, customServices = {}) {
|
|
|
89
101
|
rejectOrder: rejectOrderService,
|
|
90
102
|
discountedEntities: discountedEntitiesService,
|
|
91
103
|
createManualOrderDiscount: createManualOrderDiscountService,
|
|
104
|
+
resolveOrderItemDispatches: resolveOrderItemDispatchesService,
|
|
105
|
+
removeCartDiscount: removeCartDiscountService,
|
|
106
|
+
addMultipleCartProducts: addMultipleCartProductsService,
|
|
92
107
|
},
|
|
93
108
|
products: {
|
|
94
109
|
simulateProductPricing: simulateProductPricingService,
|
|
95
110
|
simulateProductDispatching: simulateProductDispatchingService,
|
|
96
111
|
simulateProductInventory: simulateProductInventoryService,
|
|
97
112
|
removeProduct: removeProductService,
|
|
113
|
+
findProductSiblings: findProductSiblingsService,
|
|
114
|
+
simulateConfigurablePriceRange: simulateConfigurablePriceRangeService,
|
|
98
115
|
},
|
|
99
116
|
users: {
|
|
100
117
|
migrateUserData: migrateUserDataService,
|
|
@@ -122,13 +139,22 @@ export default function initServices(modules, customServices = {}) {
|
|
|
122
139
|
invalidateFilterCache: invalidateFilterCacheService,
|
|
123
140
|
loadFilters: loadFiltersService,
|
|
124
141
|
loadFilterOptions: loadFilterOptionsService,
|
|
142
|
+
removeFilter: removeFilterService,
|
|
125
143
|
},
|
|
126
144
|
warehousing: {
|
|
127
145
|
ercMetadata: ercMetadataService,
|
|
146
|
+
resolveTokenStatus: resolveTokenStatusService,
|
|
147
|
+
isTokenInvalidateable: isTokenInvalidateableService,
|
|
128
148
|
},
|
|
129
149
|
worker: {
|
|
130
150
|
addMessage: addMessageService,
|
|
131
151
|
},
|
|
152
|
+
delivery: {
|
|
153
|
+
simulateDeliveryPricing: simulateDeliveryPricingService,
|
|
154
|
+
},
|
|
155
|
+
payment: {
|
|
156
|
+
simulatePaymentPricing: simulatePaymentPricingService,
|
|
157
|
+
},
|
|
132
158
|
};
|
|
133
159
|
return new Proxy({ ...services, ...customServices }, bindMethodsToModules(modules));
|
|
134
160
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { WarehousingProviderType } from '@unchainedshop/core-warehousing';
|
|
2
|
+
import { WarehousingDirector } from "../directors/WarehousingDirector.js";
|
|
3
|
+
export async function isTokenInvalidateableService({ token, }) {
|
|
4
|
+
const product = await this.products.findProduct({ productId: token.productId });
|
|
5
|
+
if (!product)
|
|
6
|
+
return false;
|
|
7
|
+
const virtualProviders = (await this.warehousing.allProviders()).filter(({ type }) => type === WarehousingProviderType.VIRTUAL);
|
|
8
|
+
const isInvalidateable = await WarehousingDirector.isInvalidateable(virtualProviders, {
|
|
9
|
+
token,
|
|
10
|
+
product,
|
|
11
|
+
quantity: token?.quantity || 1,
|
|
12
|
+
referenceDate: new Date(),
|
|
13
|
+
}, { modules: this });
|
|
14
|
+
return !!isInvalidateable;
|
|
15
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Modules } from '../modules.ts';
|
|
2
|
+
import { type Order, type OrderDiscount } from '@unchainedshop/core-orders';
|
|
3
|
+
export declare function removeCartDiscountService(this: Modules, { order, orderDiscount, requestContext, }: {
|
|
4
|
+
order: Order;
|
|
5
|
+
orderDiscount: OrderDiscount;
|
|
6
|
+
requestContext: {
|
|
7
|
+
localeContext: Intl.Locale;
|
|
8
|
+
userId?: string;
|
|
9
|
+
};
|
|
10
|
+
}): Promise<OrderDiscount | null>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { OrderDiscountDirector } from "../directors/index.js";
|
|
2
|
+
import { OrderDiscountTrigger } from '@unchainedshop/core-orders';
|
|
3
|
+
export async function removeCartDiscountService({ order, orderDiscount, requestContext, }) {
|
|
4
|
+
if (orderDiscount.trigger === OrderDiscountTrigger.USER) {
|
|
5
|
+
const Adapter = OrderDiscountDirector.getAdapter(orderDiscount.discountKey);
|
|
6
|
+
if (Adapter) {
|
|
7
|
+
const adapter = await Adapter.actions({
|
|
8
|
+
context: { order, orderDiscount, code: orderDiscount.code, modules: this, ...requestContext },
|
|
9
|
+
});
|
|
10
|
+
await adapter.release();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return this.orders.discounts.delete(orderDiscount._id);
|
|
14
|
+
}
|
|
@@ -4,7 +4,7 @@ export async function removeFilesService({ fileIds }) {
|
|
|
4
4
|
throw Error('Media id/s to be removed not provided as a string or array');
|
|
5
5
|
const fileUploadAdapter = getFileAdapter();
|
|
6
6
|
const fileObjects = await this.files.findFiles({
|
|
7
|
-
|
|
7
|
+
fileIds,
|
|
8
8
|
});
|
|
9
9
|
try {
|
|
10
10
|
await fileUploadAdapter.removeFiles(fileObjects, { modules: this });
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DeliveryProvider } from '@unchainedshop/core-delivery';
|
|
2
|
+
import type { OrderPosition } from '@unchainedshop/core-orders';
|
|
3
|
+
import type { Product } from '@unchainedshop/core-products';
|
|
4
|
+
import type { WarehousingProvider } from '@unchainedshop/core-warehousing';
|
|
5
|
+
import type { Modules } from '../modules.ts';
|
|
6
|
+
export interface OrderItemDispatch {
|
|
7
|
+
_id: string;
|
|
8
|
+
deliveryProvider: DeliveryProvider;
|
|
9
|
+
warehousingProvider: WarehousingProvider;
|
|
10
|
+
product: Product;
|
|
11
|
+
quantity: number;
|
|
12
|
+
countryCode: string;
|
|
13
|
+
userId: string;
|
|
14
|
+
shipping: Date;
|
|
15
|
+
earliestDelivery: Date;
|
|
16
|
+
}
|
|
17
|
+
export declare function resolveOrderItemDispatchesService(this: Modules, { orderPosition, }: {
|
|
18
|
+
orderPosition: OrderPosition;
|
|
19
|
+
}): Promise<OrderItemDispatch[] | null>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export async function resolveOrderItemDispatchesService({ orderPosition, }) {
|
|
2
|
+
const scheduling = orderPosition.scheduling || [];
|
|
3
|
+
if (!scheduling.length)
|
|
4
|
+
return [];
|
|
5
|
+
const order = await this.orders.findOrder({ orderId: orderPosition.orderId });
|
|
6
|
+
if (!order)
|
|
7
|
+
return null;
|
|
8
|
+
const { countryCode, userId, deliveryId } = order;
|
|
9
|
+
if (!deliveryId)
|
|
10
|
+
return null;
|
|
11
|
+
const orderDelivery = await this.orders.deliveries.findDelivery({
|
|
12
|
+
orderDeliveryId: deliveryId,
|
|
13
|
+
});
|
|
14
|
+
if (!orderDelivery)
|
|
15
|
+
return null;
|
|
16
|
+
const deliveryProvider = await this.delivery.findProvider({
|
|
17
|
+
deliveryProviderId: orderDelivery.deliveryProviderId,
|
|
18
|
+
});
|
|
19
|
+
if (!deliveryProvider)
|
|
20
|
+
return null;
|
|
21
|
+
const product = await this.products.findProduct({ productId: orderPosition.productId });
|
|
22
|
+
if (!product)
|
|
23
|
+
return null;
|
|
24
|
+
return Promise.all(scheduling.map(async (schedule) => {
|
|
25
|
+
const warehousingProvider = await this.warehousing.findProvider({
|
|
26
|
+
warehousingProviderId: schedule.warehousingProviderId,
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
warehousingProvider,
|
|
30
|
+
deliveryProvider,
|
|
31
|
+
product,
|
|
32
|
+
quantity: orderPosition.quantity,
|
|
33
|
+
countryCode,
|
|
34
|
+
userId,
|
|
35
|
+
...schedule,
|
|
36
|
+
};
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TokenSurrogate, TokenStatus as TokenStatusType } from '@unchainedshop/core-warehousing';
|
|
2
|
+
import type { Modules } from '../modules.ts';
|
|
3
|
+
export declare function resolveTokenStatusService(this: Modules, { token, }: {
|
|
4
|
+
token: TokenSurrogate;
|
|
5
|
+
}): Promise<TokenStatusType>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { TokenStatus } from '@unchainedshop/core-warehousing';
|
|
2
|
+
import { WorkStatus } from '@unchainedshop/core-worker';
|
|
3
|
+
export async function resolveTokenStatusService({ token, }) {
|
|
4
|
+
if (token.walletAddress && !token.userId) {
|
|
5
|
+
return TokenStatus.DECENTRALIZED;
|
|
6
|
+
}
|
|
7
|
+
const workItems = await this.worker.findWorkQueue({
|
|
8
|
+
types: ['EXPORT_TOKEN'],
|
|
9
|
+
status: [WorkStatus.NEW, WorkStatus.ALLOCATED],
|
|
10
|
+
});
|
|
11
|
+
if (workItems.find((item) => item.input?.token?._id === token._id)) {
|
|
12
|
+
return TokenStatus.EXPORTING;
|
|
13
|
+
}
|
|
14
|
+
return TokenStatus.CENTRALIZED;
|
|
15
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Product, ProductConfiguration, ProductPriceRange } from '@unchainedshop/core-products';
|
|
2
|
+
import type { User } from '@unchainedshop/core-users';
|
|
3
|
+
import type { Modules } from '../modules.ts';
|
|
4
|
+
export declare function simulateConfigurablePriceRangeService(this: Modules, { product, currencyCode, countryCode, quantity, useNetPrice, vectors, includeInactive, user, }: {
|
|
5
|
+
product: Product;
|
|
6
|
+
currencyCode: string;
|
|
7
|
+
countryCode: string;
|
|
8
|
+
quantity?: number;
|
|
9
|
+
useNetPrice?: boolean;
|
|
10
|
+
vectors?: ProductConfiguration[];
|
|
11
|
+
includeInactive?: boolean;
|
|
12
|
+
user?: User;
|
|
13
|
+
}): Promise<ProductPriceRange | null>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ProductPricingDirector } from "../core-index.js";
|
|
2
|
+
export async function simulateConfigurablePriceRangeService({ product, currencyCode, countryCode, quantity = 1, useNetPrice = false, vectors, includeInactive = false, user, }) {
|
|
3
|
+
const products = await this.products.proxyProducts(product, vectors, {
|
|
4
|
+
includeInactive,
|
|
5
|
+
});
|
|
6
|
+
const filteredPrices = (await Promise.all(products.map(async (proxyProduct) => {
|
|
7
|
+
const pricingContext = {
|
|
8
|
+
product: proxyProduct,
|
|
9
|
+
user,
|
|
10
|
+
countryCode,
|
|
11
|
+
discounts: [],
|
|
12
|
+
currencyCode,
|
|
13
|
+
quantity,
|
|
14
|
+
};
|
|
15
|
+
const calculated = await ProductPricingDirector.rebuildCalculation(pricingContext, {
|
|
16
|
+
modules: this,
|
|
17
|
+
});
|
|
18
|
+
if (!calculated || !calculated.length)
|
|
19
|
+
return null;
|
|
20
|
+
const pricing = ProductPricingDirector.calculationSheet(pricingContext, calculated);
|
|
21
|
+
const unitPrice = pricing.unitPrice({ useNetPrice });
|
|
22
|
+
return {
|
|
23
|
+
...unitPrice,
|
|
24
|
+
isNetPrice: useNetPrice,
|
|
25
|
+
isTaxable: pricing.taxSum() > 0,
|
|
26
|
+
currencyCode: pricing.currencyCode,
|
|
27
|
+
};
|
|
28
|
+
}))).filter(Boolean);
|
|
29
|
+
if (!filteredPrices.length)
|
|
30
|
+
return null;
|
|
31
|
+
const { minPrice, maxPrice } = this.products.prices.priceRange({
|
|
32
|
+
productId: product._id,
|
|
33
|
+
prices: filteredPrices,
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
minPrice,
|
|
37
|
+
maxPrice,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DeliveryProvider } from '@unchainedshop/core-delivery';
|
|
2
|
+
import type { Order } from '@unchainedshop/core-orders';
|
|
3
|
+
import type { User } from '@unchainedshop/core-users';
|
|
4
|
+
import type { Modules } from '../modules.ts';
|
|
5
|
+
export interface SimulatedDeliveryPrice {
|
|
6
|
+
amount: number;
|
|
7
|
+
currencyCode: string;
|
|
8
|
+
countryCode: string;
|
|
9
|
+
isTaxable: boolean;
|
|
10
|
+
isNetPrice: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function simulateDeliveryPricingService(this: Modules, pricingContext: {
|
|
13
|
+
currencyCode: string;
|
|
14
|
+
countryCode: string;
|
|
15
|
+
provider: DeliveryProvider;
|
|
16
|
+
providerContext?: any;
|
|
17
|
+
order?: Order;
|
|
18
|
+
user: User;
|
|
19
|
+
}, options?: {
|
|
20
|
+
useNetPrice?: boolean;
|
|
21
|
+
}): Promise<SimulatedDeliveryPrice | null>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DeliveryPricingDirector } from "../core-index.js";
|
|
2
|
+
export async function simulateDeliveryPricingService(pricingContext, options = {}) {
|
|
3
|
+
const context = {
|
|
4
|
+
currencyCode: pricingContext.currencyCode,
|
|
5
|
+
countryCode: pricingContext.countryCode,
|
|
6
|
+
provider: pricingContext.provider,
|
|
7
|
+
providerContext: pricingContext.providerContext,
|
|
8
|
+
order: pricingContext.order,
|
|
9
|
+
user: pricingContext.user,
|
|
10
|
+
};
|
|
11
|
+
const calculated = await DeliveryPricingDirector.rebuildCalculation(context, { modules: this });
|
|
12
|
+
if (!calculated?.length)
|
|
13
|
+
return null;
|
|
14
|
+
const pricing = DeliveryPricingDirector.calculationSheet(context, calculated);
|
|
15
|
+
const orderPrice = pricing.total({ useNetPrice: options.useNetPrice });
|
|
16
|
+
return {
|
|
17
|
+
amount: orderPrice.amount,
|
|
18
|
+
currencyCode: orderPrice.currencyCode,
|
|
19
|
+
countryCode: pricingContext.countryCode,
|
|
20
|
+
isTaxable: pricing.taxSum() > 0,
|
|
21
|
+
isNetPrice: options.useNetPrice || false,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PaymentProvider } from '@unchainedshop/core-payment';
|
|
2
|
+
import type { Order } from '@unchainedshop/core-orders';
|
|
3
|
+
import type { User } from '@unchainedshop/core-users';
|
|
4
|
+
import type { Modules } from '../modules.ts';
|
|
5
|
+
export interface SimulatedPaymentPrice {
|
|
6
|
+
amount: number;
|
|
7
|
+
currencyCode: string;
|
|
8
|
+
countryCode: string;
|
|
9
|
+
isTaxable: boolean;
|
|
10
|
+
isNetPrice: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function simulatePaymentPricingService(this: Modules, pricingContext: {
|
|
13
|
+
currencyCode: string;
|
|
14
|
+
countryCode: string;
|
|
15
|
+
provider: PaymentProvider;
|
|
16
|
+
providerContext?: any;
|
|
17
|
+
order?: Order;
|
|
18
|
+
user: User;
|
|
19
|
+
}, options?: {
|
|
20
|
+
useNetPrice?: boolean;
|
|
21
|
+
}): Promise<SimulatedPaymentPrice | null>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { PaymentPricingDirector } from "../core-index.js";
|
|
2
|
+
export async function simulatePaymentPricingService(pricingContext, options = {}) {
|
|
3
|
+
const context = {
|
|
4
|
+
currencyCode: pricingContext.currencyCode,
|
|
5
|
+
countryCode: pricingContext.countryCode,
|
|
6
|
+
provider: pricingContext.provider,
|
|
7
|
+
providerContext: pricingContext.providerContext,
|
|
8
|
+
order: pricingContext.order,
|
|
9
|
+
user: pricingContext.user,
|
|
10
|
+
};
|
|
11
|
+
const calculated = await PaymentPricingDirector.rebuildCalculation(context, { modules: this });
|
|
12
|
+
if (!calculated?.length)
|
|
13
|
+
return null;
|
|
14
|
+
const pricing = PaymentPricingDirector.calculationSheet(context, calculated);
|
|
15
|
+
const orderPrice = pricing.total({ useNetPrice: options.useNetPrice });
|
|
16
|
+
return {
|
|
17
|
+
amount: orderPrice.amount,
|
|
18
|
+
currencyCode: orderPrice.currencyCode,
|
|
19
|
+
countryCode: pricingContext.countryCode,
|
|
20
|
+
isTaxable: pricing.taxSum() > 0,
|
|
21
|
+
isNetPrice: options.useNetPrice || false,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -4,9 +4,9 @@ const logger = createLogger('unchained:core');
|
|
|
4
4
|
export async function updateUserAvatarAfterUploadService({ file }) {
|
|
5
5
|
const { userId } = file.meta;
|
|
6
6
|
const files = await this.files.findFiles({
|
|
7
|
-
|
|
7
|
+
excludeFileId: file._id,
|
|
8
8
|
path: file.path,
|
|
9
|
-
|
|
9
|
+
meta: { userId },
|
|
10
10
|
});
|
|
11
11
|
const fileIds = files.map((f) => f._id);
|
|
12
12
|
try {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ScheduleData {
|
|
2
|
+
schedules: {
|
|
3
|
+
s?: number[];
|
|
4
|
+
m?: number[];
|
|
5
|
+
h?: number[];
|
|
6
|
+
D?: number[];
|
|
7
|
+
M?: number[];
|
|
8
|
+
d?: number[];
|
|
9
|
+
}[];
|
|
10
|
+
}
|
|
11
|
+
declare function parseCron(cronExpr: string): ScheduleData;
|
|
12
|
+
declare function parseText(text: string): ScheduleData;
|
|
13
|
+
export declare const schedule: {
|
|
14
|
+
parse: {
|
|
15
|
+
cron: typeof parseCron;
|
|
16
|
+
text: typeof parseText;
|
|
17
|
+
};
|
|
18
|
+
schedule: (scheduleData: ScheduleData) => {
|
|
19
|
+
next: (count: number, referenceDate: Date) => Date | Date[];
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export default schedule;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
function parseCronField(field, min, max) {
|
|
2
|
+
if (field === '*')
|
|
3
|
+
return undefined;
|
|
4
|
+
const values = [];
|
|
5
|
+
const parts = field.split(',');
|
|
6
|
+
for (const part of parts) {
|
|
7
|
+
const stepMatch = part.match(/^(\d+|\*)-?(\d+)?\/(\d+)$|^(\*|\d+-\d+)\/(\d+)$/);
|
|
8
|
+
if (stepMatch || part.includes('/')) {
|
|
9
|
+
const [rangePart, stepPart] = part.split('/');
|
|
10
|
+
const step = parseInt(stepPart, 10);
|
|
11
|
+
let start = min;
|
|
12
|
+
let end = max;
|
|
13
|
+
if (rangePart !== '*') {
|
|
14
|
+
if (rangePart.includes('-')) {
|
|
15
|
+
const [rangeStart, rangeEnd] = rangePart.split('-').map(Number);
|
|
16
|
+
start = rangeStart;
|
|
17
|
+
end = rangeEnd;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
start = parseInt(rangePart, 10);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
for (let i = start; i <= end; i += step) {
|
|
24
|
+
if (!values.includes(i))
|
|
25
|
+
values.push(i);
|
|
26
|
+
}
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (part.includes('-')) {
|
|
30
|
+
const [start, end] = part.split('-').map(Number);
|
|
31
|
+
for (let i = start; i <= end; i++) {
|
|
32
|
+
if (!values.includes(i))
|
|
33
|
+
values.push(i);
|
|
34
|
+
}
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const num = parseInt(part, 10);
|
|
38
|
+
if (!isNaN(num) && !values.includes(num)) {
|
|
39
|
+
values.push(num);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return values.length > 0 ? values.sort((a, b) => a - b) : undefined;
|
|
43
|
+
}
|
|
44
|
+
function parseCron(cronExpr) {
|
|
45
|
+
const parts = cronExpr.trim().split(/\s+/);
|
|
46
|
+
if (parts.length !== 5) {
|
|
47
|
+
throw new Error(`Invalid cron expression: expected 5 fields, got ${parts.length}`);
|
|
48
|
+
}
|
|
49
|
+
const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
|
50
|
+
return {
|
|
51
|
+
schedules: [
|
|
52
|
+
{
|
|
53
|
+
s: [0],
|
|
54
|
+
m: parseCronField(minute, 0, 59),
|
|
55
|
+
h: parseCronField(hour, 0, 23),
|
|
56
|
+
D: parseCronField(dayOfMonth, 1, 31),
|
|
57
|
+
M: parseCronField(month, 1, 12),
|
|
58
|
+
d: parseCronField(dayOfWeek, 0, 6),
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function parseText(text) {
|
|
64
|
+
const match = text.toLowerCase().match(/every\s+(\d+)\s+(second|minute|hour)s?/);
|
|
65
|
+
if (!match) {
|
|
66
|
+
throw new Error(`Invalid schedule text: "${text}". Supported formats: "every N seconds/minutes/hours"`);
|
|
67
|
+
}
|
|
68
|
+
const value = parseInt(match[1], 10);
|
|
69
|
+
const unit = match[2];
|
|
70
|
+
switch (unit) {
|
|
71
|
+
case 'second': {
|
|
72
|
+
const seconds = [];
|
|
73
|
+
for (let i = 0; i < 60; i += value) {
|
|
74
|
+
seconds.push(i);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
schedules: [{ s: seconds }],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
case 'minute': {
|
|
81
|
+
const minutes = [];
|
|
82
|
+
for (let i = 0; i < 60; i += value) {
|
|
83
|
+
minutes.push(i);
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
schedules: [{ s: [0], m: minutes }],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
case 'hour': {
|
|
90
|
+
const hours = [];
|
|
91
|
+
for (let i = 0; i < 24; i += value) {
|
|
92
|
+
hours.push(i);
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
schedules: [{ s: [0], m: [0], h: hours }],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
default:
|
|
99
|
+
throw new Error(`Unsupported time unit: ${unit}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function getNextOccurrences(scheduleData, count, referenceDate) {
|
|
103
|
+
const results = [];
|
|
104
|
+
const schedule = scheduleData.schedules[0];
|
|
105
|
+
const current = new Date(referenceDate.getTime());
|
|
106
|
+
current.setMilliseconds(0);
|
|
107
|
+
current.setSeconds(current.getSeconds() + 1);
|
|
108
|
+
const maxIterations = 366 * 24 * 60 * 60;
|
|
109
|
+
let iterations = 0;
|
|
110
|
+
while (results.length < count && iterations < maxIterations) {
|
|
111
|
+
iterations++;
|
|
112
|
+
const month = current.getMonth() + 1;
|
|
113
|
+
const dayOfMonth = current.getDate();
|
|
114
|
+
const dayOfWeek = current.getDay();
|
|
115
|
+
const hour = current.getHours();
|
|
116
|
+
const minute = current.getMinutes();
|
|
117
|
+
const second = current.getSeconds();
|
|
118
|
+
const matchesMonth = !schedule.M || schedule.M.includes(month);
|
|
119
|
+
const matchesDay = !schedule.D || schedule.D.includes(dayOfMonth);
|
|
120
|
+
const matchesDayOfWeek = !schedule.d || schedule.d.includes(dayOfWeek);
|
|
121
|
+
const matchesHour = !schedule.h || schedule.h.includes(hour);
|
|
122
|
+
const matchesMinute = !schedule.m || schedule.m.includes(minute);
|
|
123
|
+
const matchesSecond = !schedule.s || schedule.s.includes(second);
|
|
124
|
+
if (matchesMonth &&
|
|
125
|
+
matchesDay &&
|
|
126
|
+
matchesDayOfWeek &&
|
|
127
|
+
matchesHour &&
|
|
128
|
+
matchesMinute &&
|
|
129
|
+
matchesSecond) {
|
|
130
|
+
results.push(new Date(current));
|
|
131
|
+
}
|
|
132
|
+
current.setSeconds(current.getSeconds() + 1);
|
|
133
|
+
}
|
|
134
|
+
return results;
|
|
135
|
+
}
|
|
136
|
+
export const schedule = {
|
|
137
|
+
parse: {
|
|
138
|
+
cron: parseCron,
|
|
139
|
+
text: parseText,
|
|
140
|
+
},
|
|
141
|
+
schedule: (scheduleData) => ({
|
|
142
|
+
next: (count, referenceDate) => {
|
|
143
|
+
const results = getNextOccurrences(scheduleData, count, referenceDate);
|
|
144
|
+
return count === 1 ? results[0] : results;
|
|
145
|
+
},
|
|
146
|
+
}),
|
|
147
|
+
};
|
|
148
|
+
export default schedule;
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"main": "lib/core-index.js",
|
|
5
5
|
"types": "lib/core-index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
7
8
|
"scripts": {
|
|
8
9
|
"clean": "tsc -b --clean",
|
|
9
10
|
"build": "tsc -b",
|
|
@@ -33,30 +34,28 @@
|
|
|
33
34
|
},
|
|
34
35
|
"homepage": "https://github.com/unchainedshop/unchained#readme",
|
|
35
36
|
"dependencies": {
|
|
36
|
-
"@
|
|
37
|
-
"@unchainedshop/core-
|
|
38
|
-
"@unchainedshop/core-
|
|
39
|
-
"@unchainedshop/core-
|
|
40
|
-
"@unchainedshop/core-
|
|
41
|
-
"@unchainedshop/core-
|
|
42
|
-
"@unchainedshop/core-
|
|
43
|
-
"@unchainedshop/core-
|
|
44
|
-
"@unchainedshop/core-
|
|
45
|
-
"@unchainedshop/core-
|
|
46
|
-
"@unchainedshop/core-
|
|
47
|
-
"@unchainedshop/core-
|
|
48
|
-
"@unchainedshop/core-
|
|
49
|
-
"@unchainedshop/core-
|
|
50
|
-
"@unchainedshop/core-
|
|
51
|
-
"@unchainedshop/core-
|
|
52
|
-
"@unchainedshop/core-
|
|
53
|
-
"@unchainedshop/
|
|
54
|
-
"@unchainedshop/
|
|
55
|
-
"@unchainedshop/utils": "^4.4.0",
|
|
37
|
+
"@unchainedshop/core-assortments": "^4.5.0",
|
|
38
|
+
"@unchainedshop/core-bookmarks": "^4.5.0",
|
|
39
|
+
"@unchainedshop/core-countries": "^4.5.0",
|
|
40
|
+
"@unchainedshop/core-currencies": "^4.5.0",
|
|
41
|
+
"@unchainedshop/core-delivery": "^4.5.0",
|
|
42
|
+
"@unchainedshop/core-enrollments": "^4.5.0",
|
|
43
|
+
"@unchainedshop/core-events": "^4.5.0",
|
|
44
|
+
"@unchainedshop/core-files": "^4.5.0",
|
|
45
|
+
"@unchainedshop/core-filters": "^4.5.0",
|
|
46
|
+
"@unchainedshop/core-languages": "^4.5.0",
|
|
47
|
+
"@unchainedshop/core-orders": "^4.5.0",
|
|
48
|
+
"@unchainedshop/core-payment": "^4.5.0",
|
|
49
|
+
"@unchainedshop/core-products": "^4.5.0",
|
|
50
|
+
"@unchainedshop/core-quotations": "^4.5.0",
|
|
51
|
+
"@unchainedshop/core-users": "^4.5.0",
|
|
52
|
+
"@unchainedshop/core-warehousing": "^4.5.0",
|
|
53
|
+
"@unchainedshop/core-worker": "^4.5.0",
|
|
54
|
+
"@unchainedshop/logger": "^4.5.0",
|
|
55
|
+
"@unchainedshop/utils": "^4.5.0",
|
|
56
56
|
"minipass-json-stream": "^1.0.2"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@types/breejs__later": "^4.1.5",
|
|
60
59
|
"@types/node": "^25.0.0",
|
|
61
60
|
"typescript": "^5.8.3"
|
|
62
61
|
}
|