@unchainedshop/platform 4.3.4 → 4.4.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/README.md +149 -2
- package/lib/context/index.d.ts +1 -2
- package/lib/context/index.js +1 -2
- package/lib/context/setAccessToken.d.ts +1 -2
- package/lib/context/setAccessToken.js +0 -1
- package/lib/migrations/createMigrationRunner.d.ts +0 -1
- package/lib/migrations/createMigrationRunner.js +0 -3
- package/lib/migrations/migrationRepository.d.ts +1 -2
- package/lib/migrations/migrationRepository.js +1 -1
- package/lib/migrations/runMigrations.d.ts +2 -3
- package/lib/migrations/runMigrations.js +1 -2
- package/lib/platform-index.d.ts +4 -5
- package/lib/platform-index.js +4 -5
- package/lib/setup/setupAccounts.d.ts +1 -2
- package/lib/setup/setupAccounts.js +0 -1
- package/lib/setup/setupTemplates.d.ts +11 -11
- package/lib/setup/setupTemplates.js +16 -19
- package/lib/setup/setupUploadHandlers.d.ts +1 -2
- package/lib/setup/setupUploadHandlers.js +0 -1
- package/lib/setup/setupWorkqueue.d.ts +2 -3
- package/lib/setup/setupWorkqueue.js +1 -7
- package/lib/startPlatform.d.ts +6 -7
- package/lib/startPlatform.js +15 -16
- package/lib/templates/index.d.ts +8 -9
- package/lib/templates/index.js +8 -9
- package/lib/templates/order-parser/getOrderPositionsData.d.ts +2 -3
- package/lib/templates/order-parser/getOrderPositionsData.js +0 -1
- package/lib/templates/order-parser/getOrderSummaryData.d.ts +2 -3
- package/lib/templates/order-parser/getOrderSummaryData.js +0 -1
- package/lib/templates/order-parser/index.d.ts +4 -5
- package/lib/templates/order-parser/index.js +2 -3
- package/lib/templates/resolveAccountActionTemplate.d.ts +1 -2
- package/lib/templates/resolveAccountActionTemplate.js +0 -2
- package/lib/templates/resolveEnrollmentStatusTemplate.d.ts +1 -2
- package/lib/templates/resolveEnrollmentStatusTemplate.js +0 -1
- package/lib/templates/resolveErrorReportTemplate.d.ts +1 -2
- package/lib/templates/resolveErrorReportTemplate.js +0 -1
- package/lib/templates/resolveForwardDeliveryTemplate.d.ts +1 -2
- package/lib/templates/resolveForwardDeliveryTemplate.js +1 -2
- package/lib/templates/resolveOrderConfirmationTemplate.d.ts +1 -2
- package/lib/templates/resolveOrderConfirmationTemplate.js +1 -2
- package/lib/templates/resolveOrderRejectionTemplate.d.ts +1 -2
- package/lib/templates/resolveOrderRejectionTemplate.js +1 -2
- package/lib/templates/resolveQuotationStatusTemplate.d.ts +1 -2
- package/lib/templates/resolveQuotationStatusTemplate.js +0 -1
- package/package.json +17 -16
- package/lib/context/index.d.ts.map +0 -1
- package/lib/context/index.js.map +0 -1
- package/lib/context/setAccessToken.d.ts.map +0 -1
- package/lib/context/setAccessToken.js.map +0 -1
- package/lib/migrations/createMigrationRunner.d.ts.map +0 -1
- package/lib/migrations/createMigrationRunner.js.map +0 -1
- package/lib/migrations/migrationRepository.d.ts.map +0 -1
- package/lib/migrations/migrationRepository.js.map +0 -1
- package/lib/migrations/runMigrations.d.ts.map +0 -1
- package/lib/migrations/runMigrations.js.map +0 -1
- package/lib/platform-index.d.ts.map +0 -1
- package/lib/platform-index.js.map +0 -1
- package/lib/setup/setupAccounts.d.ts.map +0 -1
- package/lib/setup/setupAccounts.js.map +0 -1
- package/lib/setup/setupTemplates.d.ts.map +0 -1
- package/lib/setup/setupTemplates.js.map +0 -1
- package/lib/setup/setupUploadHandlers.d.ts.map +0 -1
- package/lib/setup/setupUploadHandlers.js.map +0 -1
- package/lib/setup/setupWorkqueue.d.ts.map +0 -1
- package/lib/setup/setupWorkqueue.js.map +0 -1
- package/lib/startPlatform.d.ts.map +0 -1
- package/lib/startPlatform.js.map +0 -1
- package/lib/templates/index.d.ts.map +0 -1
- package/lib/templates/index.js.map +0 -1
- package/lib/templates/order-parser/getOrderPositionsData.d.ts.map +0 -1
- package/lib/templates/order-parser/getOrderPositionsData.js.map +0 -1
- package/lib/templates/order-parser/getOrderSummaryData.d.ts.map +0 -1
- package/lib/templates/order-parser/getOrderSummaryData.js.map +0 -1
- package/lib/templates/order-parser/index.d.ts.map +0 -1
- package/lib/templates/order-parser/index.js.map +0 -1
- package/lib/templates/resolveAccountActionTemplate.d.ts.map +0 -1
- package/lib/templates/resolveAccountActionTemplate.js.map +0 -1
- package/lib/templates/resolveEnrollmentStatusTemplate.d.ts.map +0 -1
- package/lib/templates/resolveEnrollmentStatusTemplate.js.map +0 -1
- package/lib/templates/resolveErrorReportTemplate.d.ts.map +0 -1
- package/lib/templates/resolveErrorReportTemplate.js.map +0 -1
- package/lib/templates/resolveForwardDeliveryTemplate.d.ts.map +0 -1
- package/lib/templates/resolveForwardDeliveryTemplate.js.map +0 -1
- package/lib/templates/resolveOrderConfirmationTemplate.d.ts.map +0 -1
- package/lib/templates/resolveOrderConfirmationTemplate.js.map +0 -1
- package/lib/templates/resolveOrderRejectionTemplate.d.ts.map +0 -1
- package/lib/templates/resolveOrderRejectionTemplate.js.map +0 -1
- package/lib/templates/resolveQuotationStatusTemplate.d.ts.map +0 -1
- package/lib/templates/resolveQuotationStatusTemplate.js.map +0 -1
- package/src/context/index.ts +0 -1
- package/src/context/setAccessToken.ts +0 -22
- package/src/migrations/createMigrationRunner.ts +0 -65
- package/src/migrations/migrationRepository.ts +0 -22
- package/src/migrations/runMigrations.ts +0 -68
- package/src/platform-index.ts +0 -19
- package/src/setup/setupAccounts.ts +0 -11
- package/src/setup/setupTemplates.ts +0 -67
- package/src/setup/setupUploadHandlers.ts +0 -22
- package/src/setup/setupWorkqueue.ts +0 -104
- package/src/startPlatform.ts +0 -128
- package/src/templates/index.ts +0 -9
- package/src/templates/order-parser/getOrderPositionsData.ts +0 -50
- package/src/templates/order-parser/getOrderSummaryData.ts +0 -91
- package/src/templates/order-parser/index.ts +0 -65
- package/src/templates/resolveAccountActionTemplate.ts +0 -127
- package/src/templates/resolveEnrollmentStatusTemplate.ts +0 -34
- package/src/templates/resolveErrorReportTemplate.ts +0 -47
- package/src/templates/resolveForwardDeliveryTemplate.ts +0 -42
- package/src/templates/resolveOrderConfirmationTemplate.ts +0 -40
- package/src/templates/resolveOrderRejectionTemplate.ts +0 -41
- package/src/templates/resolveQuotationStatusTemplate.ts +0 -45
- package/tests/platform-index.test.ts +0 -7
- package/tsconfig.json +0 -9
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { UnchainedCore } from '@unchainedshop/core';
|
|
2
|
-
import { subscribe } from '@unchainedshop/events';
|
|
3
|
-
|
|
4
|
-
export const setupAccounts = (unchainedAPI: UnchainedCore) => {
|
|
5
|
-
subscribe('USER_ACCOUNT_ACTION', async ({ payload }: { payload: any }) => {
|
|
6
|
-
await unchainedAPI.services.worker.addMessage('ACCOUNT_ACTION', {
|
|
7
|
-
recipientEmail: payload.address,
|
|
8
|
-
...payload,
|
|
9
|
-
});
|
|
10
|
-
});
|
|
11
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { MessagingDirector, UnchainedCore } from '@unchainedshop/core';
|
|
2
|
-
import { subscribe } from '@unchainedshop/events';
|
|
3
|
-
import { Order, OrderStatus } from '@unchainedshop/core-orders';
|
|
4
|
-
import { RawPayloadType } from '@unchainedshop/events';
|
|
5
|
-
import { resolveOrderRejectionTemplate } from '../templates/resolveOrderRejectionTemplate.js';
|
|
6
|
-
import { resolveAccountActionTemplate } from '../templates/resolveAccountActionTemplate.js';
|
|
7
|
-
import { resolveForwardDeliveryTemplate } from '../templates/resolveForwardDeliveryTemplate.js';
|
|
8
|
-
import { resolveOrderConfirmationTemplate } from '../templates/resolveOrderConfirmationTemplate.js';
|
|
9
|
-
import { resolveQuotationStatusTemplate } from '../templates/resolveQuotationStatusTemplate.js';
|
|
10
|
-
import { resolveEnrollmentStatusTemplate } from '../templates/resolveEnrollmentStatusTemplate.js';
|
|
11
|
-
import { resolveErrorReportTemplate } from '../templates/resolveErrorReportTemplate.js';
|
|
12
|
-
|
|
13
|
-
export enum MessageTypes {
|
|
14
|
-
ACCOUNT_ACTION = 'ACCOUNT_ACTION',
|
|
15
|
-
DELIVERY = 'DELIVERY',
|
|
16
|
-
ORDER_CONFIRMATION = 'ORDER_CONFIRMATION',
|
|
17
|
-
ORDER_REJECTION = 'ORDER_REJECTION',
|
|
18
|
-
QUOTATION_STATUS = 'QUOTATION_STATUS',
|
|
19
|
-
ENROLLMENT_STATUS = 'ENROLLMENT_STATUS',
|
|
20
|
-
ERROR_REPORT = 'ERROR_REPORT',
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export const setupTemplates = (unchainedAPI: UnchainedCore) => {
|
|
24
|
-
MessagingDirector.registerTemplate(MessageTypes.ACCOUNT_ACTION, resolveAccountActionTemplate);
|
|
25
|
-
MessagingDirector.registerTemplate(MessageTypes.DELIVERY, resolveForwardDeliveryTemplate);
|
|
26
|
-
MessagingDirector.registerTemplate(MessageTypes.ORDER_CONFIRMATION, resolveOrderConfirmationTemplate);
|
|
27
|
-
MessagingDirector.registerTemplate(MessageTypes.ORDER_REJECTION, resolveOrderRejectionTemplate);
|
|
28
|
-
MessagingDirector.registerTemplate(MessageTypes.QUOTATION_STATUS, resolveQuotationStatusTemplate);
|
|
29
|
-
MessagingDirector.registerTemplate(MessageTypes.ENROLLMENT_STATUS, resolveEnrollmentStatusTemplate);
|
|
30
|
-
MessagingDirector.registerTemplate(MessageTypes.ERROR_REPORT, resolveErrorReportTemplate);
|
|
31
|
-
|
|
32
|
-
subscribe('ORDER_CHECKOUT', async ({ payload }: RawPayloadType<{ order: Order }>) => {
|
|
33
|
-
const { order } = payload;
|
|
34
|
-
const user = await unchainedAPI.modules.users.findUserById(order.userId);
|
|
35
|
-
const locale = unchainedAPI.modules.users.userLocale(user);
|
|
36
|
-
|
|
37
|
-
if (order.status === OrderStatus.PENDING) {
|
|
38
|
-
// We only send the "confirmation" when pending, else we let the other events handle it
|
|
39
|
-
await unchainedAPI.services.worker.addMessage(MessageTypes.ORDER_CONFIRMATION, {
|
|
40
|
-
locale: locale.baseName,
|
|
41
|
-
orderId: order._id,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
subscribe('ORDER_CONFIRMED', async ({ payload }: RawPayloadType<{ order: Order }>) => {
|
|
47
|
-
const { order } = payload;
|
|
48
|
-
const user = await unchainedAPI.modules.users.findUserById(order.userId);
|
|
49
|
-
const locale = unchainedAPI.modules.users.userLocale(user);
|
|
50
|
-
|
|
51
|
-
await unchainedAPI.services.worker.addMessage(MessageTypes.ORDER_CONFIRMATION, {
|
|
52
|
-
locale: locale.baseName,
|
|
53
|
-
orderId: order._id,
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
subscribe('ORDER_REJECTED', async ({ payload }: RawPayloadType<{ order: Order }>) => {
|
|
58
|
-
const { order } = payload;
|
|
59
|
-
const user = await unchainedAPI.modules.users.findUserById(order.userId);
|
|
60
|
-
const locale = unchainedAPI.modules.users.userLocale(user);
|
|
61
|
-
|
|
62
|
-
await unchainedAPI.services.worker.addMessage(MessageTypes.ORDER_REJECTION, {
|
|
63
|
-
locale: locale.baseName,
|
|
64
|
-
orderId: order._id,
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { UnchainedCore } from '@unchainedshop/core';
|
|
2
|
-
import { FileDirector } from '@unchainedshop/file-upload';
|
|
3
|
-
|
|
4
|
-
export const setupUploadHandlers = ({ services, modules }: UnchainedCore) => {
|
|
5
|
-
FileDirector.registerFileUploadCallback('user-avatars', async (file) => {
|
|
6
|
-
return services.users.updateUserAvatarAfterUpload({ file });
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
FileDirector.registerFileUploadCallback('product-media', async (file) => {
|
|
10
|
-
await modules.products.media.create({
|
|
11
|
-
productId: file.meta?.productId as string,
|
|
12
|
-
mediaId: file._id,
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
FileDirector.registerFileUploadCallback('assortment-media', async (file) => {
|
|
17
|
-
await modules.assortments.media.create({
|
|
18
|
-
assortmentId: file.meta?.assortmentId as string,
|
|
19
|
-
mediaId: file._id,
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
};
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EventListenerWorker,
|
|
3
|
-
FailedRescheduler,
|
|
4
|
-
FailedReschedulerParams,
|
|
5
|
-
IntervalWorker,
|
|
6
|
-
IntervalWorkerParams,
|
|
7
|
-
IScheduler,
|
|
8
|
-
IWorker,
|
|
9
|
-
UnchainedCore,
|
|
10
|
-
} from '@unchainedshop/core';
|
|
11
|
-
import { runMigrations } from '../migrations/runMigrations.js';
|
|
12
|
-
import { MigrationRepository } from '@unchainedshop/mongodb';
|
|
13
|
-
import { createLogger } from '@unchainedshop/logger';
|
|
14
|
-
const logger = createLogger('unchained:worker');
|
|
15
|
-
|
|
16
|
-
export type WorkQueueQueueManager = IWorker<any> | IScheduler<any>;
|
|
17
|
-
export interface SetupWorkqueueOptions extends IntervalWorkerParams, FailedReschedulerParams {
|
|
18
|
-
enabledQueueManagers?: WorkQueueQueueManager[];
|
|
19
|
-
invalidateProviders?: boolean;
|
|
20
|
-
providerInvalidationMaxAgeDays?: number;
|
|
21
|
-
assignCartForUsers?: boolean;
|
|
22
|
-
disableWorker?: boolean;
|
|
23
|
-
skipInvalidationOnStartup?: boolean;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const {
|
|
27
|
-
UNCHAINED_DISABLE_PROVIDER_INVALIDATION,
|
|
28
|
-
UNCHAINED_DISABLE_WORKER,
|
|
29
|
-
UNCHAINED_ASSIGN_CART_FOR_USERS,
|
|
30
|
-
} = process.env;
|
|
31
|
-
|
|
32
|
-
export const defaultQueueManagers: WorkQueueQueueManager[] = [
|
|
33
|
-
FailedRescheduler,
|
|
34
|
-
EventListenerWorker,
|
|
35
|
-
IntervalWorker,
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
export const queueWorkers: any[] = [];
|
|
39
|
-
|
|
40
|
-
export async function setupWorkqueue({
|
|
41
|
-
unchainedAPI,
|
|
42
|
-
migrationRepository,
|
|
43
|
-
...workQueueOptions
|
|
44
|
-
}: {
|
|
45
|
-
unchainedAPI: UnchainedCore;
|
|
46
|
-
migrationRepository: MigrationRepository<UnchainedCore>;
|
|
47
|
-
} & SetupWorkqueueOptions) {
|
|
48
|
-
if (workQueueOptions.disableWorker || UNCHAINED_DISABLE_WORKER) return;
|
|
49
|
-
|
|
50
|
-
// Run migrations
|
|
51
|
-
await runMigrations({ migrationRepository, unchainedAPI });
|
|
52
|
-
|
|
53
|
-
// Start queue managers
|
|
54
|
-
(workQueueOptions?.enabledQueueManagers || defaultQueueManagers).forEach((f) => {
|
|
55
|
-
const handler = f.actions(workQueueOptions, unchainedAPI);
|
|
56
|
-
queueWorkers.push(handler);
|
|
57
|
-
handler.start();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// Invalidate providers on carts
|
|
61
|
-
if (workQueueOptions.invalidateProviders ?? !UNCHAINED_DISABLE_PROVIDER_INVALIDATION) {
|
|
62
|
-
const orders = await unchainedAPI.modules.orders.findCartsToInvalidate(
|
|
63
|
-
workQueueOptions.providerInvalidationMaxAgeDays,
|
|
64
|
-
);
|
|
65
|
-
await Promise.allSettled(
|
|
66
|
-
orders.map(async (order) => {
|
|
67
|
-
await unchainedAPI.services.orders.updateCalculation(order._id);
|
|
68
|
-
}),
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Ensure users have carts
|
|
73
|
-
if (workQueueOptions.assignCartForUsers ?? Boolean(UNCHAINED_ASSIGN_CART_FOR_USERS)) {
|
|
74
|
-
const users = await unchainedAPI.modules.users.findUsers({});
|
|
75
|
-
|
|
76
|
-
await Promise.all(
|
|
77
|
-
users.map((user) => {
|
|
78
|
-
const locale = unchainedAPI.modules.users.userLocale(user);
|
|
79
|
-
if (!locale.region) return null;
|
|
80
|
-
return unchainedAPI.services.orders.nextUserCart({
|
|
81
|
-
user,
|
|
82
|
-
countryCode: locale.region,
|
|
83
|
-
});
|
|
84
|
-
}),
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Setup filter cache
|
|
89
|
-
if (!workQueueOptions?.skipInvalidationOnStartup) {
|
|
90
|
-
unchainedAPI.services.filters
|
|
91
|
-
.invalidateFilterCache()
|
|
92
|
-
.then(() => {
|
|
93
|
-
logger.info('Filter cache rebuilt');
|
|
94
|
-
})
|
|
95
|
-
.catch(logger.warn);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function stopWorkqueue() {
|
|
100
|
-
queueWorkers.forEach((worker) => {
|
|
101
|
-
worker?.stop();
|
|
102
|
-
});
|
|
103
|
-
queueWorkers.length = 0;
|
|
104
|
-
}
|
package/src/startPlatform.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { startAPIServer, roles, UnchainedServerOptions } from '@unchainedshop/api';
|
|
2
|
-
import { initCore, UnchainedCoreOptions } from '@unchainedshop/core';
|
|
3
|
-
import { initDb, mongodb, stopDb } from '@unchainedshop/mongodb';
|
|
4
|
-
import { defaultLogger } from '@unchainedshop/logger';
|
|
5
|
-
import { UnchainedCore } from '@unchainedshop/core';
|
|
6
|
-
import { setupAccounts } from './setup/setupAccounts.js';
|
|
7
|
-
import { setupUploadHandlers } from './setup/setupUploadHandlers.js';
|
|
8
|
-
import { setupTemplates, MessageTypes } from './setup/setupTemplates.js';
|
|
9
|
-
import { SetupWorkqueueOptions, stopWorkqueue, setupWorkqueue } from './setup/setupWorkqueue.js';
|
|
10
|
-
import { createMigrationRepository } from './migrations/migrationRepository.js';
|
|
11
|
-
import { IRoleOptionConfig } from '@unchainedshop/roles';
|
|
12
|
-
|
|
13
|
-
export { MessageTypes };
|
|
14
|
-
|
|
15
|
-
export type PlatformOptions = {
|
|
16
|
-
rolesOptions?: IRoleOptionConfig;
|
|
17
|
-
workQueueOptions?: SetupWorkqueueOptions;
|
|
18
|
-
} & Omit<UnchainedCoreOptions, 'migrationRepository' | 'db'> &
|
|
19
|
-
Omit<UnchainedServerOptions, 'roles' | 'unchainedAPI'>;
|
|
20
|
-
|
|
21
|
-
const REQUIRED_ENV_VARIABLES = [
|
|
22
|
-
'EMAIL_WEBSITE_NAME',
|
|
23
|
-
'EMAIL_WEBSITE_URL',
|
|
24
|
-
'EMAIL_FROM',
|
|
25
|
-
'ROOT_URL',
|
|
26
|
-
'UNCHAINED_TOKEN_SECRET',
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
const exitOnMissingEnvironmentVariables = () => {
|
|
30
|
-
const failedEnv = REQUIRED_ENV_VARIABLES.filter((key) => !process.env[key]);
|
|
31
|
-
if (failedEnv.length > 0) {
|
|
32
|
-
defaultLogger.error(`Missing required environment variables at boot time: ${failedEnv.join(', ')}`);
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const existOnInvalidEnvironmentVariables = () => {
|
|
38
|
-
if ((process.env?.UNCHAINED_TOKEN_SECRET || '').length < 32) {
|
|
39
|
-
defaultLogger.error(
|
|
40
|
-
'UNCHAINED_TOKEN_SECRET must be assigned a string that has a length of 32 or greater',
|
|
41
|
-
);
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const startPlatform = async ({
|
|
47
|
-
modules,
|
|
48
|
-
services,
|
|
49
|
-
options,
|
|
50
|
-
rolesOptions,
|
|
51
|
-
bulkImporter,
|
|
52
|
-
workQueueOptions,
|
|
53
|
-
...arbitraryAPIServerConfiguration
|
|
54
|
-
}: PlatformOptions): Promise<{
|
|
55
|
-
unchainedAPI: UnchainedCore;
|
|
56
|
-
graphqlHandler: any;
|
|
57
|
-
db: mongodb.Db;
|
|
58
|
-
}> => {
|
|
59
|
-
const start = performance.now();
|
|
60
|
-
|
|
61
|
-
exitOnMissingEnvironmentVariables();
|
|
62
|
-
existOnInvalidEnvironmentVariables();
|
|
63
|
-
|
|
64
|
-
const configuredRoles = roles.configureRoles(rolesOptions || {});
|
|
65
|
-
|
|
66
|
-
// Configure database
|
|
67
|
-
const db = await initDb();
|
|
68
|
-
|
|
69
|
-
// Prepare Migrations
|
|
70
|
-
const migrationRepository = createMigrationRepository(db);
|
|
71
|
-
|
|
72
|
-
// Initialise core api using the database
|
|
73
|
-
const unchainedAPI = await initCore({
|
|
74
|
-
db,
|
|
75
|
-
migrationRepository,
|
|
76
|
-
bulkImporter,
|
|
77
|
-
modules,
|
|
78
|
-
services,
|
|
79
|
-
options,
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// Setup Accounts specific extensions and event handlers
|
|
83
|
-
setupAccounts(unchainedAPI);
|
|
84
|
-
|
|
85
|
-
// Setup Messaging Templates
|
|
86
|
-
setupTemplates(unchainedAPI);
|
|
87
|
-
|
|
88
|
-
// Setup File Upload Handlers
|
|
89
|
-
setupUploadHandlers(unchainedAPI);
|
|
90
|
-
|
|
91
|
-
// Start GraphQL Server
|
|
92
|
-
const graphqlHandler = await startAPIServer({
|
|
93
|
-
unchainedAPI,
|
|
94
|
-
roles: configuredRoles,
|
|
95
|
-
...arbitraryAPIServerConfiguration,
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// Setup Work Queue
|
|
99
|
-
await setupWorkqueue({
|
|
100
|
-
unchainedAPI,
|
|
101
|
-
migrationRepository,
|
|
102
|
-
...workQueueOptions,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
const { default: packageJson } = await import(`${import.meta.dirname}/../package.json`, {
|
|
106
|
-
with: { type: 'json' },
|
|
107
|
-
});
|
|
108
|
-
defaultLogger.info(`Unchained Engine running`, { version: packageJson.version });
|
|
109
|
-
|
|
110
|
-
const cleanup = (signal) => async () => {
|
|
111
|
-
defaultLogger.debug('Stopping Workqueue', { signal });
|
|
112
|
-
stopWorkqueue();
|
|
113
|
-
defaultLogger.debug('Stopping GraphQL server', { signal });
|
|
114
|
-
await graphqlHandler.dispose();
|
|
115
|
-
defaultLogger.debug('Stopping DB Connection', { signal });
|
|
116
|
-
await stopDb();
|
|
117
|
-
defaultLogger.debug(`Unchained Engine exiting`, { signal, version: packageJson.version });
|
|
118
|
-
process.exit(0);
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
process.on('SIGTERM', cleanup('SIGTERM'));
|
|
122
|
-
process.on('SIGINT', cleanup('SIGINT'));
|
|
123
|
-
|
|
124
|
-
const end = performance.now();
|
|
125
|
-
defaultLogger.debug(`Unchained Engine started in ${(end - start).toFixed(0)} ms`);
|
|
126
|
-
|
|
127
|
-
return { unchainedAPI, graphqlHandler, db };
|
|
128
|
-
};
|
package/src/templates/index.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export { resolveOrderRejectionTemplate } from './resolveOrderRejectionTemplate.js';
|
|
2
|
-
export { resolveAccountActionTemplate } from './resolveAccountActionTemplate.js';
|
|
3
|
-
export { resolveForwardDeliveryTemplate } from './resolveForwardDeliveryTemplate.js';
|
|
4
|
-
export { resolveOrderConfirmationTemplate } from './resolveOrderConfirmationTemplate.js';
|
|
5
|
-
export { resolveQuotationStatusTemplate } from './resolveQuotationStatusTemplate.js';
|
|
6
|
-
export { resolveEnrollmentStatusTemplate } from './resolveEnrollmentStatusTemplate.js';
|
|
7
|
-
export { resolveErrorReportTemplate } from './resolveErrorReportTemplate.js';
|
|
8
|
-
|
|
9
|
-
export * as parser from './order-parser/index.js';
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { UnchainedCore } from '@unchainedshop/core';
|
|
2
|
-
import { Order } from '@unchainedshop/core-orders';
|
|
3
|
-
import { ProductPricingSheet } from '@unchainedshop/core';
|
|
4
|
-
import { ch } from '@unchainedshop/utils';
|
|
5
|
-
|
|
6
|
-
type PriceFormatter = ({ amount, currencyCode }: { amount: number; currencyCode: string }) => string;
|
|
7
|
-
|
|
8
|
-
export const getOrderPositionsData = async (
|
|
9
|
-
order: Order,
|
|
10
|
-
params: { locale: Intl.Locale; useNetPrice?: boolean; format?: PriceFormatter },
|
|
11
|
-
context: UnchainedCore,
|
|
12
|
-
) => {
|
|
13
|
-
const { modules } = context;
|
|
14
|
-
const { useNetPrice, format = ch.priceToString } = params || {};
|
|
15
|
-
const orderPositions = await modules.orders.positions.findOrderPositions({
|
|
16
|
-
orderId: order._id,
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
return Promise.all(
|
|
20
|
-
orderPositions.map(async (orderPosition) => {
|
|
21
|
-
const productTexts = await modules.products.texts.findLocalizedText({
|
|
22
|
-
productId: orderPosition.productId,
|
|
23
|
-
locale: params.locale,
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
const positionPricing = ProductPricingSheet({
|
|
27
|
-
calculation: orderPosition.calculation,
|
|
28
|
-
currencyCode: order.currencyCode,
|
|
29
|
-
quantity: orderPosition.quantity,
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
const total = positionPricing.total({ useNetPrice });
|
|
33
|
-
const unitPrice = positionPricing.unitPrice({ useNetPrice });
|
|
34
|
-
|
|
35
|
-
const { quantity } = positionPricing;
|
|
36
|
-
return {
|
|
37
|
-
productId: orderPosition.productId,
|
|
38
|
-
configuration: orderPosition.configuration,
|
|
39
|
-
productTexts,
|
|
40
|
-
quantity,
|
|
41
|
-
rawPrices: {
|
|
42
|
-
unitPrice,
|
|
43
|
-
total,
|
|
44
|
-
},
|
|
45
|
-
unitPrice: format(unitPrice),
|
|
46
|
-
total: format(total),
|
|
47
|
-
};
|
|
48
|
-
}),
|
|
49
|
-
);
|
|
50
|
-
};
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { Order } from '@unchainedshop/core-orders';
|
|
2
|
-
import { UnchainedCore, OrderPricingSheet, OrderPricingRowCategory } from '@unchainedshop/core';
|
|
3
|
-
import { ch } from '@unchainedshop/utils';
|
|
4
|
-
|
|
5
|
-
type PriceFormatter = ({ amount, currencyCode }: { amount: number; currencyCode: string }) => string;
|
|
6
|
-
|
|
7
|
-
export const getOrderSummaryData = async (
|
|
8
|
-
order: Order,
|
|
9
|
-
params: { locale: Intl.Locale; useNetPrice?: boolean; format?: PriceFormatter },
|
|
10
|
-
context: UnchainedCore,
|
|
11
|
-
) => {
|
|
12
|
-
const { modules } = context;
|
|
13
|
-
const { useNetPrice, format = ch.priceToString } = params || {};
|
|
14
|
-
const orderDelivery =
|
|
15
|
-
order.deliveryId &&
|
|
16
|
-
(await modules.orders.deliveries.findDelivery({
|
|
17
|
-
orderDeliveryId: order.deliveryId,
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
|
-
if (!orderDelivery) throw new Error('Order delivery not found');
|
|
21
|
-
|
|
22
|
-
const orderPayment =
|
|
23
|
-
order.paymentId &&
|
|
24
|
-
(await modules.orders.payments.findOrderPayment({
|
|
25
|
-
orderPaymentId: order.paymentId,
|
|
26
|
-
}));
|
|
27
|
-
|
|
28
|
-
if (!orderPayment) throw new Error('Order payment not found');
|
|
29
|
-
|
|
30
|
-
const paymentProvider = await modules.payment.paymentProviders.findProvider({
|
|
31
|
-
paymentProviderId: orderPayment.paymentProviderId,
|
|
32
|
-
});
|
|
33
|
-
const deliveryProvider = await modules.delivery.findProvider({
|
|
34
|
-
deliveryProviderId: orderDelivery.deliveryProviderId,
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
const deliveryAddress = ch.addressToString(
|
|
38
|
-
orderDelivery?.context?.deliveryAddress || order.billingAddress,
|
|
39
|
-
);
|
|
40
|
-
const billingAddress = ch.addressToString(order.billingAddress);
|
|
41
|
-
const orderPricing = OrderPricingSheet({
|
|
42
|
-
calculation: order.calculation,
|
|
43
|
-
currencyCode: order.currencyCode,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const paymentTotal = orderPricing.total({
|
|
47
|
-
category: OrderPricingRowCategory.Payment,
|
|
48
|
-
useNetPrice,
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
const deliveryTotal = orderPricing.total({
|
|
52
|
-
category: OrderPricingRowCategory.Delivery,
|
|
53
|
-
useNetPrice,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
const taxesTotal = orderPricing.total({
|
|
57
|
-
category: OrderPricingRowCategory.Taxes,
|
|
58
|
-
useNetPrice,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
const itemsTotal = orderPricing.total({
|
|
62
|
-
category: OrderPricingRowCategory.Items,
|
|
63
|
-
useNetPrice,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
const total = orderPricing.total({ useNetPrice });
|
|
67
|
-
|
|
68
|
-
const payment = paymentProvider?.adapterKey;
|
|
69
|
-
const delivery = deliveryProvider?.adapterKey;
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
rawPrices: {
|
|
73
|
-
items: itemsTotal,
|
|
74
|
-
taxes: taxesTotal,
|
|
75
|
-
delivery: deliveryTotal,
|
|
76
|
-
payment: paymentTotal,
|
|
77
|
-
gross: total,
|
|
78
|
-
},
|
|
79
|
-
prices: {
|
|
80
|
-
items: format(itemsTotal),
|
|
81
|
-
taxes: format(taxesTotal),
|
|
82
|
-
delivery: format(deliveryTotal),
|
|
83
|
-
payment: format(paymentTotal),
|
|
84
|
-
gross: format(total),
|
|
85
|
-
},
|
|
86
|
-
payment,
|
|
87
|
-
delivery,
|
|
88
|
-
deliveryAddress,
|
|
89
|
-
billingAddress,
|
|
90
|
-
};
|
|
91
|
-
};
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { getOrderPositionsData } from './getOrderPositionsData.js';
|
|
2
|
-
import { getOrderSummaryData } from './getOrderSummaryData.js';
|
|
3
|
-
import { Order } from '@unchainedshop/core-orders';
|
|
4
|
-
import { UnchainedCore } from '@unchainedshop/core';
|
|
5
|
-
|
|
6
|
-
export const transformOrderToText = async (
|
|
7
|
-
{ order, locale }: { order: Order; locale: Intl.Locale },
|
|
8
|
-
context: UnchainedCore,
|
|
9
|
-
) => {
|
|
10
|
-
const orderDate = new Date(order.ordered!).toLocaleString();
|
|
11
|
-
const orderNumber = order.orderNumber;
|
|
12
|
-
const summary = await getOrderSummaryData(order, { locale }, context);
|
|
13
|
-
const positions = await getOrderPositionsData(order, { locale }, context);
|
|
14
|
-
|
|
15
|
-
const positionsText = positions
|
|
16
|
-
.map((pos) => ` ${pos.quantity}x ${pos.productTexts.title} ${pos.total}`)
|
|
17
|
-
.join('\n');
|
|
18
|
-
|
|
19
|
-
const subtotalText = summary.rawPrices.items.amount ? ` Subtotal ${summary.prices.items}\n` : '';
|
|
20
|
-
const deliveryFeesText = summary.rawPrices.delivery.amount
|
|
21
|
-
? ` Delivery ${summary.prices.delivery}\n`
|
|
22
|
-
: '';
|
|
23
|
-
const paymentFeesText = summary.rawPrices.payment.amount
|
|
24
|
-
? ` Payment ${summary.prices.payment}\n`
|
|
25
|
-
: '';
|
|
26
|
-
const totalLine = ` ${'─'.repeat(50)}\n Order Total ${summary.prices.gross}`;
|
|
27
|
-
const taxesText = summary.rawPrices.taxes.amount ? `\n (incl. VAT ${summary.prices.taxes})` : '';
|
|
28
|
-
|
|
29
|
-
return `═════════════════════════════════════════════════════
|
|
30
|
-
ORDER CONFIRMATION
|
|
31
|
-
═════════════════════════════════════════════════════
|
|
32
|
-
|
|
33
|
-
Order Number: ${orderNumber}
|
|
34
|
-
Order Date: ${orderDate}
|
|
35
|
-
|
|
36
|
-
─────────────────────────────────────────────────────
|
|
37
|
-
DELIVERY INFORMATION
|
|
38
|
-
─────────────────────────────────────────────────────
|
|
39
|
-
|
|
40
|
-
Delivery Method: ${summary.delivery}
|
|
41
|
-
|
|
42
|
-
Delivery Address:
|
|
43
|
-
${summary.deliveryAddress}
|
|
44
|
-
|
|
45
|
-
─────────────────────────────────────────────────────
|
|
46
|
-
PAYMENT INFORMATION
|
|
47
|
-
─────────────────────────────────────────────────────
|
|
48
|
-
|
|
49
|
-
Payment Method: ${summary.payment}
|
|
50
|
-
|
|
51
|
-
Billing Address:
|
|
52
|
-
${summary.billingAddress}
|
|
53
|
-
|
|
54
|
-
─────────────────────────────────────────────────────
|
|
55
|
-
ORDER DETAILS
|
|
56
|
-
─────────────────────────────────────────────────────
|
|
57
|
-
|
|
58
|
-
${positionsText}
|
|
59
|
-
|
|
60
|
-
${subtotalText}${deliveryFeesText}${paymentFeesText}${totalLine}${taxesText}
|
|
61
|
-
═════════════════════════════════════════════════════
|
|
62
|
-
`;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export { getOrderPositionsData, getOrderSummaryData };
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { TemplateResolver } from '@unchainedshop/core';
|
|
2
|
-
|
|
3
|
-
const { EMAIL_FROM, EMAIL_WEBSITE_URL, EMAIL_WEBSITE_NAME } = process.env;
|
|
4
|
-
|
|
5
|
-
const verifyEmailEnglishConfig = {
|
|
6
|
-
buttonText: 'Verify email address',
|
|
7
|
-
message: 'We need to ensure that this email is yours as a commercial partner.',
|
|
8
|
-
subject: `${EMAIL_WEBSITE_NAME}: Verify your email address`,
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const passwordChangedEmailEnglishConfig = {
|
|
12
|
-
message: `
|
|
13
|
-
Your account password has been successfully changed.\n
|
|
14
|
-
`,
|
|
15
|
-
subject: `${EMAIL_WEBSITE_NAME}: Your password has been changed`,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const buildTextTemplate = ({
|
|
19
|
-
message,
|
|
20
|
-
buttonText,
|
|
21
|
-
url,
|
|
22
|
-
}: {
|
|
23
|
-
message: string;
|
|
24
|
-
buttonText: string;
|
|
25
|
-
url: string | null;
|
|
26
|
-
}) => {
|
|
27
|
-
const urlSection = url
|
|
28
|
-
? `
|
|
29
|
-
|
|
30
|
-
-----------------
|
|
31
|
-
${buttonText}: ${url}
|
|
32
|
-
-----------------
|
|
33
|
-
`
|
|
34
|
-
: '';
|
|
35
|
-
|
|
36
|
-
return ` ${message}${urlSection}`;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const emailConfig = {
|
|
40
|
-
'enroll-account': {
|
|
41
|
-
url: (token) => `${EMAIL_WEBSITE_URL}/enroll-account?token=${token}`,
|
|
42
|
-
en: {
|
|
43
|
-
buttonText: 'Set password',
|
|
44
|
-
message: `${EMAIL_WEBSITE_NAME} has set up an user account for you. Please click below to set up a password and to finish the registration.`,
|
|
45
|
-
subject: `${EMAIL_WEBSITE_NAME}: You got a new account`,
|
|
46
|
-
},
|
|
47
|
-
de: {
|
|
48
|
-
buttonText: 'Passwort setzen',
|
|
49
|
-
message: `${EMAIL_WEBSITE_NAME} hat für dich ein Benutzerkonto angelegt. Bitte klicke unten um ein Passwort zu setzen und damit die Registrierung abzuschliessen.`,
|
|
50
|
-
subject: `${EMAIL_WEBSITE_NAME}: Für dich wurde ein Konto eingerichtet`,
|
|
51
|
-
},
|
|
52
|
-
fr: {
|
|
53
|
-
buttonText: 'Set password',
|
|
54
|
-
message: `${EMAIL_WEBSITE_NAME} has set up an user account for you. Please click below to set up a password and to finish the registration.`,
|
|
55
|
-
subject: `${EMAIL_WEBSITE_NAME}: You got a new account`,
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
'reset-password': {
|
|
59
|
-
url: (token) => `${EMAIL_WEBSITE_URL}/reset-password?token=${token}`,
|
|
60
|
-
en: {
|
|
61
|
-
buttonText: 'Set new password',
|
|
62
|
-
message: `
|
|
63
|
-
Click on „Set new password". If you don’t want to set a new password, just ignore this email.\n
|
|
64
|
-
`,
|
|
65
|
-
subject: `${EMAIL_WEBSITE_NAME}: Set password`,
|
|
66
|
-
},
|
|
67
|
-
de: {
|
|
68
|
-
buttonText: 'Neues Passwort setzen',
|
|
69
|
-
message: `
|
|
70
|
-
Klicke auf „Neues Passwort setzen", um ein neues Passwort anzulegen.\n
|
|
71
|
-
Falls du dein Passwort nicht zurücksetzen möchtest, ignoriere dieses E-Mail einfach.\n
|
|
72
|
-
`,
|
|
73
|
-
subject: `${EMAIL_WEBSITE_NAME}: Passwort zurücksetzen`,
|
|
74
|
-
},
|
|
75
|
-
fr: {
|
|
76
|
-
buttonText: 'Set new password',
|
|
77
|
-
message: `
|
|
78
|
-
Click on „Set new password". If you don’t want to set a new password, just ignore this email.\n
|
|
79
|
-
`,
|
|
80
|
-
subject: `${EMAIL_WEBSITE_NAME}: Set password`,
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
'verify-email': {
|
|
84
|
-
url: (token) => `${EMAIL_WEBSITE_URL}/verify-email?token=${token}`,
|
|
85
|
-
en: verifyEmailEnglishConfig,
|
|
86
|
-
de: verifyEmailEnglishConfig,
|
|
87
|
-
fr: verifyEmailEnglishConfig,
|
|
88
|
-
},
|
|
89
|
-
'': {
|
|
90
|
-
// password changed!
|
|
91
|
-
url: () => null,
|
|
92
|
-
en: passwordChangedEmailEnglishConfig,
|
|
93
|
-
de: passwordChangedEmailEnglishConfig,
|
|
94
|
-
fr: passwordChangedEmailEnglishConfig,
|
|
95
|
-
},
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
export const resolveAccountActionTemplate: TemplateResolver = async (
|
|
99
|
-
{ userId, action, recipientEmail, token },
|
|
100
|
-
{ modules },
|
|
101
|
-
) => {
|
|
102
|
-
if (!token || !action) return [];
|
|
103
|
-
|
|
104
|
-
const user = await modules.users.findUserById(userId);
|
|
105
|
-
const locale = modules.users.userLocale(user);
|
|
106
|
-
|
|
107
|
-
const { url } = emailConfig[action];
|
|
108
|
-
const { subject, message, buttonText } = emailConfig[action][locale.language];
|
|
109
|
-
|
|
110
|
-
const text = buildTextTemplate({
|
|
111
|
-
buttonText,
|
|
112
|
-
message,
|
|
113
|
-
url: url(token),
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
return [
|
|
117
|
-
{
|
|
118
|
-
type: 'EMAIL',
|
|
119
|
-
input: {
|
|
120
|
-
from: EMAIL_FROM || 'noreply@unchained.local',
|
|
121
|
-
to: recipientEmail || modules.users.primaryEmail(user)?.address,
|
|
122
|
-
subject,
|
|
123
|
-
text,
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
];
|
|
127
|
-
};
|