@unchainedshop/platform 4.4.0 → 4.6.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.
@@ -41,7 +41,7 @@ export const createMigrationRunner = ({ currentId, logger = console, migrationRe
41
41
  return [mostRecentId, migrations.length];
42
42
  }
43
43
  catch (e) {
44
- logger.error(e.name, e);
44
+ logger.error(`Migration failed: ${e.name} - ${e.message}`);
45
45
  return [e.migrationId, null];
46
46
  }
47
47
  },
@@ -1,5 +1,4 @@
1
1
  export * from './startPlatform.ts';
2
- export * from './context/index.ts';
3
2
  export * from './templates/index.ts';
4
3
  export * from './migrations/runMigrations.ts';
5
4
  export declare const printRuntimeConfiguration: () => void;
@@ -1,5 +1,4 @@
1
1
  export * from "./startPlatform.js";
2
- export * from "./context/index.js";
3
2
  export * from "./templates/index.js";
4
3
  export * from "./migrations/runMigrations.js";
5
4
  import { MessagingDirector, getAllAdapters } from '@unchainedshop/core';
@@ -1,11 +1,3 @@
1
- var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
- if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
- return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
- return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
- });
6
- }
7
- return path;
8
- };
9
1
  import { startAPIServer, roles } from '@unchainedshop/api';
10
2
  import { initCore } from '@unchainedshop/core';
11
3
  import { initDb, mongodb, stopDb } from '@unchainedshop/mongodb';
@@ -15,6 +7,7 @@ import { setupUploadHandlers } from "./setup/setupUploadHandlers.js";
15
7
  import { setupTemplates, MessageTypes } from "./setup/setupTemplates.js";
16
8
  import { stopWorkqueue, setupWorkqueue } from "./setup/setupWorkqueue.js";
17
9
  import { createMigrationRepository } from "./migrations/migrationRepository.js";
10
+ const { UNCHAINED_API_VERSION, npm_package_version } = process.env;
18
11
  export { MessageTypes };
19
12
  const REQUIRED_ENV_VARIABLES = [
20
13
  'EMAIL_WEBSITE_NAME',
@@ -23,6 +16,7 @@ const REQUIRED_ENV_VARIABLES = [
23
16
  'ROOT_URL',
24
17
  'UNCHAINED_TOKEN_SECRET',
25
18
  ];
19
+ const CLEANUP_FORCE_EXIT_TIMEOUT_MS = 15000;
26
20
  const exitOnMissingEnvironmentVariables = () => {
27
21
  const failedEnv = REQUIRED_ENV_VARIABLES.filter((key) => !process.env[key]);
28
22
  if (failedEnv.length > 0) {
@@ -64,22 +58,53 @@ export const startPlatform = async ({ modules, services, options, rolesOptions,
64
58
  migrationRepository,
65
59
  ...workQueueOptions,
66
60
  });
67
- const { default: packageJson } = await import(__rewriteRelativeImportExtension(`${import.meta.dirname}/../package.json`), {
68
- with: { type: 'json' },
69
- });
70
- defaultLogger.info(`Unchained Engine running`, { version: packageJson.version });
61
+ const version = UNCHAINED_API_VERSION || npm_package_version || 'n/a';
62
+ defaultLogger.info(`Unchained Engine running`, { version });
63
+ let isCleaningUp = false;
71
64
  const cleanup = (signal) => async () => {
72
- defaultLogger.debug('Stopping Workqueue', { signal });
73
- stopWorkqueue();
74
- defaultLogger.debug('Stopping GraphQL server', { signal });
75
- await graphqlHandler.dispose();
76
- defaultLogger.debug('Stopping DB Connection', { signal });
77
- await stopDb();
78
- defaultLogger.debug(`Unchained Engine exiting`, { signal, version: packageJson.version });
79
- process.exit(0);
65
+ if (isCleaningUp) {
66
+ defaultLogger.debug('Cleanup already in progress, ignoring signal', { signal });
67
+ return;
68
+ }
69
+ isCleaningUp = true;
70
+ defaultLogger.debug('Starting cleanup', { signal });
71
+ const forceExitTimeout = setTimeout(() => {
72
+ defaultLogger.error('Cleanup timeout exceeded, forcing exit');
73
+ process.exit(1);
74
+ }, CLEANUP_FORCE_EXIT_TIMEOUT_MS);
75
+ forceExitTimeout.unref();
76
+ try {
77
+ defaultLogger.debug('Stopping Workqueue', { signal });
78
+ stopWorkqueue();
79
+ defaultLogger.debug('Stopping GraphQL server', { signal });
80
+ await graphqlHandler.dispose();
81
+ defaultLogger.debug('Stopping DB Connection', { signal });
82
+ await stopDb();
83
+ defaultLogger.debug(`Unchained Engine exiting gracefully`, { signal, version });
84
+ clearTimeout(forceExitTimeout);
85
+ process.exit(0);
86
+ }
87
+ catch (error) {
88
+ defaultLogger.error('Error during cleanup', {
89
+ signal,
90
+ error: error instanceof Error ? error.message : String(error),
91
+ });
92
+ clearTimeout(forceExitTimeout);
93
+ process.exit(1);
94
+ }
80
95
  };
81
96
  process.on('SIGTERM', cleanup('SIGTERM'));
82
97
  process.on('SIGINT', cleanup('SIGINT'));
98
+ process.on('uncaughtException', async (error) => {
99
+ defaultLogger.error('Uncaught exception', { error: error.message, stack: error.stack });
100
+ await cleanup('uncaughtException')();
101
+ });
102
+ process.on('unhandledRejection', async (reason) => {
103
+ defaultLogger.error('Unhandled rejection', {
104
+ reason: reason instanceof Error ? reason.message : String(reason),
105
+ });
106
+ await cleanup('unhandledRejection')();
107
+ });
83
108
  const end = performance.now();
84
109
  defaultLogger.debug(`Unchained Engine started in ${(end - start).toFixed(0)} ms`);
85
110
  return { unchainedAPI, graphqlHandler, db };
@@ -11,7 +11,7 @@ export const resolveOrderRejectionTemplate = async ({ orderId, locale }, context
11
11
  const text = `
12
12
  I'm sorry we can't confirm your order.
13
13
 
14
- This can happen when the payment was not successful or the order was manually canceled because of product availability or fullfillment issues.
14
+ This can happen when the payment was not successful or the order was manually canceled because of product availability or fulfillment issues.
15
15
 
16
16
  The order in question is:
17
17
 
@@ -2,12 +2,6 @@ const { EMAIL_FROM, EMAIL_WEBSITE_NAME, EMAIL_WEBSITE_URL } = process.env;
2
2
  export const resolveQuotationStatusTemplate = async ({ quotationId }, { modules }) => {
3
3
  const quotation = await modules.quotations.findQuotation({ quotationId });
4
4
  const user = await modules.users.findUserById(quotation.userId);
5
- const attachments = (await modules.files.findFiles({ 'meta.quotationId': quotation._id, 'meta.type': 'PROPOSAL' }, { sort: { 'meta.date': -1 } }))
6
- .filter(Boolean)
7
- .map((file) => ({
8
- filename: `${quotation.quotationNumber}_${file.name}`,
9
- path: file.url,
10
- }));
11
5
  const subject = `${EMAIL_WEBSITE_NAME}: Updated Quotation / ${quotation.quotationNumber}`;
12
6
  const url = `${EMAIL_WEBSITE_URL}/quotation?_id=${quotation._id}`;
13
7
  const text = `
@@ -27,7 +21,6 @@ export const resolveQuotationStatusTemplate = async ({ quotationId }, { modules
27
21
  to: modules.users.primaryEmail(user)?.address,
28
22
  subject,
29
23
  text,
30
- attachments,
31
24
  },
32
25
  },
33
26
  ];
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@unchainedshop/platform",
3
- "version": "4.4.0",
3
+ "description": "Complete e-commerce platform bundle for the Unchained Engine",
4
+ "version": "4.6.0",
4
5
  "main": "lib/platform-index.js",
5
6
  "types": "lib/platform-index.d.ts",
6
7
  "type": "module",
@@ -37,15 +38,15 @@
37
38
  "npm": ">=10.0.0"
38
39
  },
39
40
  "dependencies": {
40
- "@unchainedshop/api": "^4.4.0",
41
- "@unchainedshop/core": "^4.4.0",
42
- "@unchainedshop/events": "^4.4.0",
43
- "@unchainedshop/file-upload": "^4.4.0",
44
- "@unchainedshop/logger": "^4.4.0",
45
- "@unchainedshop/mongodb": "^4.4.0",
46
- "@unchainedshop/plugins": "^4.4.0",
47
- "@unchainedshop/roles": "^4.4.0",
48
- "@unchainedshop/utils": "^4.4.0",
41
+ "@unchainedshop/api": "^4.6.0",
42
+ "@unchainedshop/core": "^4.6.0",
43
+ "@unchainedshop/events": "^4.6.0",
44
+ "@unchainedshop/file-upload": "^4.6.0",
45
+ "@unchainedshop/logger": "^4.6.0",
46
+ "@unchainedshop/mongodb": "^4.6.0",
47
+ "@unchainedshop/plugins": "^4.6.0",
48
+ "@unchainedshop/roles": "^4.6.0",
49
+ "@unchainedshop/utils": "^4.6.0",
49
50
  "safe-stable-stringify": "^2.5.0"
50
51
  },
51
52
  "devDependencies": {
@@ -1 +0,0 @@
1
- export { default as setAccessToken } from './setAccessToken.ts';
@@ -1 +0,0 @@
1
- export { default as setAccessToken } from "./setAccessToken.js";
@@ -1,3 +0,0 @@
1
- import type { UnchainedCore } from '@unchainedshop/core';
2
- declare const _default: (unchainedAPI: UnchainedCore, username: string, plainSecret: string) => Promise<void>;
3
- export default _default;
@@ -1,11 +0,0 @@
1
- import { sha256 } from '@unchainedshop/utils';
2
- export default async (unchainedAPI, username, plainSecret) => {
3
- const secret = await sha256(`${username}:${plainSecret}`);
4
- await unchainedAPI.modules.users.updateUser({ username }, {
5
- $set: {
6
- 'services.token': {
7
- secret,
8
- },
9
- },
10
- }, {});
11
- };