@unchainedshop/api 4.0.0-rc.13 → 4.0.0-rc.15

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.
Files changed (108) hide show
  1. package/lib/express/createERCMetadataMiddleware.d.ts.map +1 -1
  2. package/lib/express/createERCMetadataMiddleware.js +10 -9
  3. package/lib/express/createERCMetadataMiddleware.js.map +1 -1
  4. package/lib/fastify/bulkImportHandler.js +1 -1
  5. package/lib/fastify/bulkImportHandler.js.map +1 -1
  6. package/lib/fastify/ercMetadataHandler.js +1 -1
  7. package/lib/fastify/ercMetadataHandler.js.map +1 -1
  8. package/lib/fastify/tempUploadHandler.js +1 -1
  9. package/lib/fastify/tempUploadHandler.js.map +1 -1
  10. package/lib/mcp/tools/order/schemas.d.ts +2 -2
  11. package/lib/mcp/tools/product/schemas.d.ts +62 -62
  12. package/lib/mcp/tools/system/schemas.d.ts +36 -6
  13. package/lib/mcp/tools/system/schemas.d.ts.map +1 -1
  14. package/lib/mcp/tools/system/schemas.js +4 -6
  15. package/lib/mcp/tools/system/schemas.js.map +1 -1
  16. package/lib/mcp/tools/system/types.d.ts +8 -2
  17. package/lib/mcp/tools/system/types.d.ts.map +1 -1
  18. package/lib/mcp/tools/users/schemas.d.ts +2 -2
  19. package/lib/resolvers/mutations/accounts/verifyWeb3Address.d.ts.map +1 -1
  20. package/lib/resolvers/mutations/accounts/verifyWeb3Address.js +78 -5
  21. package/lib/resolvers/mutations/accounts/verifyWeb3Address.js.map +1 -1
  22. package/lib/resolvers/mutations/index.d.ts +4 -1
  23. package/lib/resolvers/mutations/index.d.ts.map +1 -1
  24. package/lib/resolvers/mutations/index.js +8 -2
  25. package/lib/resolvers/mutations/index.js.map +1 -1
  26. package/lib/resolvers/mutations/orders/updateCart.js +6 -6
  27. package/lib/resolvers/mutations/orders/updateCart.js.map +1 -1
  28. package/lib/resolvers/mutations/orders/updateCartDeliveryPickUp.d.ts +8 -0
  29. package/lib/resolvers/mutations/orders/updateCartDeliveryPickUp.d.ts.map +1 -0
  30. package/lib/resolvers/mutations/orders/updateCartDeliveryPickUp.js +38 -0
  31. package/lib/resolvers/mutations/orders/updateCartDeliveryPickUp.js.map +1 -0
  32. package/lib/resolvers/mutations/orders/updateCartDeliveryShipping.d.ts +8 -0
  33. package/lib/resolvers/mutations/orders/updateCartDeliveryShipping.d.ts.map +1 -0
  34. package/lib/resolvers/mutations/orders/updateCartDeliveryShipping.js +38 -0
  35. package/lib/resolvers/mutations/orders/updateCartDeliveryShipping.js.map +1 -0
  36. package/lib/resolvers/mutations/orders/updateCartPaymentGeneric.d.ts +7 -0
  37. package/lib/resolvers/mutations/orders/updateCartPaymentGeneric.d.ts.map +1 -0
  38. package/lib/resolvers/mutations/orders/updateCartPaymentGeneric.js +37 -0
  39. package/lib/resolvers/mutations/orders/updateCartPaymentGeneric.js.map +1 -0
  40. package/lib/resolvers/mutations/orders/updateCartPaymentInvoice.d.ts +7 -0
  41. package/lib/resolvers/mutations/orders/updateCartPaymentInvoice.d.ts.map +1 -0
  42. package/lib/resolvers/mutations/orders/updateCartPaymentInvoice.js +37 -0
  43. package/lib/resolvers/mutations/orders/updateCartPaymentInvoice.js.map +1 -0
  44. package/lib/resolvers/mutations/products/updateProductCommerce.d.ts.map +1 -1
  45. package/lib/resolvers/mutations/products/updateProductCommerce.js +11 -2
  46. package/lib/resolvers/mutations/products/updateProductCommerce.js.map +1 -1
  47. package/lib/resolvers/queries/orders/orderStatistics.d.ts +3 -1
  48. package/lib/resolvers/queries/orders/orderStatistics.d.ts.map +1 -1
  49. package/lib/resolvers/queries/orders/orderStatistics.js +3 -2
  50. package/lib/resolvers/queries/orders/orderStatistics.js.map +1 -1
  51. package/lib/resolvers/type/index.d.ts +52 -0
  52. package/lib/resolvers/type/index.d.ts.map +1 -1
  53. package/lib/resolvers/type/index.js +2 -0
  54. package/lib/resolvers/type/index.js.map +1 -1
  55. package/lib/resolvers/type/order/order-payment-types.d.ts.map +1 -1
  56. package/lib/resolvers/type/order/order-payment-types.js +0 -1
  57. package/lib/resolvers/type/order/order-payment-types.js.map +1 -1
  58. package/lib/resolvers/type/order/order-statistics-types.d.ts +34 -0
  59. package/lib/resolvers/type/order/order-statistics-types.d.ts.map +1 -0
  60. package/lib/resolvers/type/order/order-statistics-types.js +68 -0
  61. package/lib/resolvers/type/order/order-statistics-types.js.map +1 -0
  62. package/lib/resolvers/type/product/product-bundle-types.d.ts +20 -0
  63. package/lib/resolvers/type/product/product-bundle-types.d.ts.map +1 -1
  64. package/lib/resolvers/type/product/product-bundle-types.js +2 -2
  65. package/lib/resolvers/type/product/product-bundle-types.js.map +1 -1
  66. package/lib/schema/mutation.d.ts.map +1 -1
  67. package/lib/schema/mutation.js +36 -7
  68. package/lib/schema/mutation.js.map +1 -1
  69. package/lib/schema/query.js +2 -2
  70. package/lib/schema/types/events.d.ts.map +1 -1
  71. package/lib/schema/types/events.js +7 -1
  72. package/lib/schema/types/events.js.map +1 -1
  73. package/lib/schema/types/order/order.d.ts.map +1 -1
  74. package/lib/schema/types/order/order.js +9 -1
  75. package/lib/schema/types/order/order.js.map +1 -1
  76. package/lib/schema/types/payment.d.ts.map +1 -1
  77. package/lib/schema/types/payment.js +0 -5
  78. package/lib/schema/types/payment.js.map +1 -1
  79. package/lib/schema/types/product/bundle-product.d.ts.map +1 -1
  80. package/lib/schema/types/product/bundle-product.js +18 -7
  81. package/lib/schema/types/product/bundle-product.js.map +1 -1
  82. package/package.json +17 -12
  83. package/src/express/createERCMetadataMiddleware.ts +11 -9
  84. package/src/fastify/bulkImportHandler.ts +1 -1
  85. package/src/fastify/ercMetadataHandler.ts +1 -1
  86. package/src/fastify/tempUploadHandler.ts +1 -1
  87. package/src/mcp/tools/system/schemas.ts +4 -6
  88. package/src/mcp/tools/system/types.ts +8 -2
  89. package/src/resolvers/mutations/accounts/verifyWeb3Address.ts +100 -7
  90. package/src/resolvers/mutations/index.ts +8 -2
  91. package/src/resolvers/mutations/orders/updateCart.ts +6 -6
  92. package/src/resolvers/mutations/orders/updateCartDeliveryPickUp.ts +51 -0
  93. package/src/resolvers/mutations/orders/updateCartDeliveryShipping.ts +51 -0
  94. package/src/resolvers/mutations/orders/updateCartPaymentGeneric.ts +50 -0
  95. package/src/resolvers/mutations/orders/updateCartPaymentInvoice.ts +50 -0
  96. package/src/resolvers/mutations/products/updateProductCommerce.ts +12 -4
  97. package/src/resolvers/queries/orders/orderStatistics.ts +3 -3
  98. package/src/resolvers/type/index.ts +2 -0
  99. package/src/resolvers/type/order/order-payment-types.ts +0 -1
  100. package/src/resolvers/type/order/order-statistics-types.ts +99 -0
  101. package/src/resolvers/type/product/product-bundle-types.ts +2 -2
  102. package/src/schema/mutation.ts +36 -7
  103. package/src/schema/query.ts +2 -2
  104. package/src/schema/types/events.ts +7 -1
  105. package/src/schema/types/order/order.ts +9 -1
  106. package/src/schema/types/payment.ts +0 -5
  107. package/src/schema/types/product/bundle-product.ts +18 -7
  108. package/src/resolvers/mutations/orders/updateOrderPaymentCard.ts +0 -37
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unchainedshop/api",
3
- "version": "4.0.0-rc.13",
3
+ "version": "4.0.0-rc.15",
4
4
  "main": "lib/api-index.js",
5
5
  "types": "lib/api-index.d.ts",
6
6
  "type": "module",
@@ -31,7 +31,6 @@
31
31
  },
32
32
  "homepage": "https://github.com/unchainedshop/unchained#readme",
33
33
  "peerDependencies": {
34
- "@ethereumjs/util": ">= 10 < 11",
35
34
  "fastify": ">= 5.2 < 6",
36
35
  "@fastify/cookie": ">= 11 < 12",
37
36
  "@fastify/session": ">= 11 < 12",
@@ -42,7 +41,9 @@
42
41
  "express-session": ">= 1.18 < 2",
43
42
  "multer": ">= 2 < 3",
44
43
  "graphql-yoga": ">= 5.9 < 6",
45
- "passport": ">= 0.7 < 1"
44
+ "passport": ">= 0.7 < 1",
45
+ "@noble/curves": "^2.0.0",
46
+ "@noble/hashes": "^2.0.0"
46
47
  },
47
48
  "peerDependenciesMeta": {
48
49
  "@modelcontextprotocol/sdk": {
@@ -54,9 +55,6 @@
54
55
  "connect-mongo": {
55
56
  "optional": false
56
57
  },
57
- "@ethereumjs/util": {
58
- "optional": true
59
- },
60
58
  "fastify": {
61
59
  "optional": true
62
60
  },
@@ -80,14 +78,20 @@
80
78
  },
81
79
  "passport": {
82
80
  "optional": true
81
+ },
82
+ "@noble/curves": {
83
+ "optional": true
84
+ },
85
+ "@noble/hashes": {
86
+ "optional": true
83
87
  }
84
88
  },
85
89
  "dependencies": {
86
- "@unchainedshop/core": "^4.0.0-rc.13",
87
- "@unchainedshop/events": "^4.0.0-rc.13",
88
- "@unchainedshop/logger": "^4.0.0-rc.13",
89
- "@unchainedshop/roles": "^4.0.0-rc.13",
90
- "@unchainedshop/utils": "^4.0.0-rc.13",
90
+ "@unchainedshop/core": "^4.0.0-rc.15",
91
+ "@unchainedshop/events": "^4.0.0-rc.15",
92
+ "@unchainedshop/logger": "^4.0.0-rc.15",
93
+ "@unchainedshop/roles": "^4.0.0-rc.15",
94
+ "@unchainedshop/utils": "^4.0.0-rc.15",
91
95
  "accounting": "0.4.1",
92
96
  "dataloader": "^2.2.3",
93
97
  "expiry-map": "^2.0.0",
@@ -97,7 +101,8 @@
97
101
  "zod": "^3.25.76"
98
102
  },
99
103
  "devDependencies": {
100
- "@ethereumjs/util": "^10.0.0",
104
+ "@noble/curves": "^2.0.0",
105
+ "@noble/hashes": "^2.0.0",
101
106
  "@fastify/cookie": "^11.0.2",
102
107
  "@fastify/multipart": "^9.0.3",
103
108
  "@fastify/session": "^11.1.0",
@@ -1,4 +1,3 @@
1
- import path from 'node:path';
2
1
  import { createLogger } from '@unchainedshop/logger';
3
2
  import { Context } from '../context.js';
4
3
  import { Request, RequestHandler } from 'express';
@@ -25,16 +24,20 @@ const ercMetadataMiddleware: RequestHandler = async (
25
24
 
26
25
  const { services, modules, loaders, locale } = req.unchainedContext;
27
26
  const url = new URL(req.url, ROOT_URL);
28
- const parsedPath = path.parse(url.pathname);
29
27
 
30
- if (parsedPath.ext !== '.json') throw new Error('Invalid ERC Metadata URI');
28
+ // Replace path.parse with URL/string methods
29
+ const pathname = url.pathname;
30
+ if (!pathname.toLowerCase().endsWith('.json')) throw new Error('Invalid ERC Metadata URI');
31
+
32
+ const fileName = pathname.split('/').pop();
33
+ const chainTokenId = fileName.slice(0, fileName.lastIndexOf('.'));
31
34
 
32
35
  const [, productId, localeOrTokenFilename, tokenFileName] = url.pathname.split('/');
33
36
 
34
37
  const product = await loaders.productLoader.load({ productId });
35
38
 
36
39
  const [token] = await modules.warehousing.findTokens({
37
- chainTokenId: parsedPath.name,
40
+ chainTokenId,
38
41
  contractAddress: product?.tokenization?.contractAddress,
39
42
  });
40
43
 
@@ -49,11 +52,10 @@ const ercMetadataMiddleware: RequestHandler = async (
49
52
  }
50
53
 
51
54
  const body = JSON.stringify(ercMetadata);
52
- res.writeHead(200, {
53
- 'Content-Length': Buffer.byteLength(body),
54
- 'Content-Type': 'text/plain',
55
- });
56
- res.end(body);
55
+ res.status(200);
56
+ res.setHeader('Content-Type', 'application/json');
57
+ res.setHeader('Content-Length', new TextEncoder().encode(body).length);
58
+ return res.send(body);
57
59
  } catch (e) {
58
60
  logger.error(e.message);
59
61
  res.writeHead(503);
@@ -46,7 +46,7 @@ const bulkImportHandler: RouteHandlerMethod = async (
46
46
 
47
47
  const body = JSON.stringify(work);
48
48
  res.status(200);
49
- res.header('Content-Length', Buffer.byteLength(body));
49
+ res.header('Content-Length', new TextEncoder().encode(body).length);
50
50
  res.header('Content-Type', 'application/json');
51
51
  return res.send(body);
52
52
  } catch (e) {
@@ -41,7 +41,7 @@ const ercMetadataHandler: RouteHandlerMethod = async (
41
41
 
42
42
  const body = JSON.stringify(ercMetadata);
43
43
  res.status(200);
44
- res.header('Content-Length', Buffer.byteLength(body));
44
+ res.header('Content-Length', new TextEncoder().encode(body).length);
45
45
  res.header('Content-Type', 'application/json');
46
46
  return res.send(body);
47
47
  } catch (e) {
@@ -39,7 +39,7 @@ const tempUploadHandler: RouteHandlerMethod = async (
39
39
  const url = context.modules.files.normalizeUrl(rawUrl, {});
40
40
  const body = JSON.stringify({ fileId: file._id, url, expires: expires.toISOString() });
41
41
  res.status(200);
42
- res.header('Content-Length', Buffer.byteLength(body));
42
+ res.header('Content-Length', new TextEncoder().encode(body).length);
43
43
  res.header('Content-Type', 'application/json');
44
44
  return res.send(body);
45
45
  } catch (e) {
@@ -183,10 +183,9 @@ export const actionValidators = {
183
183
  .optional()
184
184
  .describe('Filter events by specific event types (e.g., USER_CREATED, ORDER_PLACED)'),
185
185
  created: z
186
- .string()
187
- .datetime()
186
+ .object(DateRangeSchema)
188
187
  .optional()
189
- .describe('ISO 8601 timestamp to filter events created on or after this date/time'),
188
+ .describe('Date range filter for when events are emitted/created'),
190
189
  }),
191
190
 
192
191
  EVENT_COUNT: z.object({
@@ -196,10 +195,9 @@ export const actionValidators = {
196
195
  .optional()
197
196
  .describe('Filter events by specific event types (e.g., USER_CREATED, ORDER_PLACED)'),
198
197
  created: z
199
- .string()
200
- .datetime()
198
+ .object(DateRangeSchema)
201
199
  .optional()
202
- .describe('ISO 8601 timestamp to filter events created on or after this date/time'),
200
+ .describe('Date range filter for when events are emitted/created'),
203
201
  }),
204
202
 
205
203
  EVENT_STATISTICS: z.object({
@@ -30,11 +30,17 @@ export interface EventListOptions {
30
30
  queryString?: string;
31
31
  types?: string[];
32
32
  sort?: SortOption[];
33
- created?: Date;
33
+ created?: {
34
+ start?: Date;
35
+ end?: Date;
36
+ };
34
37
  }
35
38
 
36
39
  export interface EventCountOptions {
37
40
  queryString?: string;
38
- created?: Date;
41
+ created?: {
42
+ start?: Date;
43
+ end?: Date;
44
+ };
39
45
  types?: string[];
40
46
  }
@@ -2,6 +2,93 @@ import { log } from '@unchainedshop/logger';
2
2
  import { UserWeb3AddressNotFoundError, UserWeb3AddressSignatureError } from '../../../errors.js';
3
3
  import { Context } from '../../../context.js';
4
4
 
5
+ import type { keccak_256 as Keccak256Type } from '@noble/hashes/sha3.js';
6
+ import type { bytesToHex as BytesToHex, hexToBytes as HexToBytes } from '@noble/hashes/utils.js';
7
+ import type { secp256k1 as Secp256k1Type } from '@noble/curves/secp256k1.js';
8
+
9
+ // Dynamic imports for optional peer dependencies
10
+ let secp256k1: typeof Secp256k1Type;
11
+ let keccak_256: typeof Keccak256Type;
12
+ let bytesToHex: typeof BytesToHex;
13
+ let hexToBytes: typeof HexToBytes;
14
+
15
+ async function loadNoblePackages() {
16
+ try {
17
+ // eslint-disable-next-line
18
+ // @ts-ignore
19
+ const curves = await import('@noble/curves/secp256k1.js');
20
+
21
+ // eslint-disable-next-line
22
+ // @ts-ignore
23
+ const hashes = await import('@noble/hashes/sha3.js');
24
+
25
+ // eslint-disable-next-line
26
+ // @ts-ignore
27
+ const utils = await import('@noble/hashes/utils.js');
28
+
29
+ if (!curves || !hashes || !utils) {
30
+ throw new Error('Missing required @noble packages for Web3 signature verification');
31
+ }
32
+
33
+ secp256k1 = curves.secp256k1;
34
+ keccak_256 = hashes.keccak_256;
35
+ bytesToHex = utils.bytesToHex;
36
+ hexToBytes = utils.hexToBytes;
37
+
38
+ return true;
39
+ } catch (error) {
40
+ log('Failed to load @noble packages for Web3 verification', { error: error.message });
41
+ return false;
42
+ }
43
+ }
44
+
45
+ // Inline utility functions to replace @ethereumjs/util
46
+ function fromRPCSig(sig: string): { v: bigint; r: Uint8Array; s: Uint8Array } {
47
+ const bytes = hexToBytes(sig.startsWith('0x') ? sig.slice(2) : sig);
48
+ if (bytes.length !== 65) throw new Error('Invalid signature length');
49
+
50
+ const r = bytes.slice(0, 32);
51
+ const s = bytes.slice(32, 64);
52
+ let v = BigInt(bytes[64]);
53
+
54
+ // Handle EIP-155 encoding
55
+ if (v >= 35n) {
56
+ v = v - 35n - 2n * 1n; // chainId = 1 for mainnet, adjust if needed
57
+ } else if (v >= 27n) {
58
+ v = v - 27n;
59
+ }
60
+
61
+ return { v, r, s };
62
+ }
63
+
64
+ function hashPersonalMessage(message: Uint8Array): Uint8Array {
65
+ const prefix = new TextEncoder().encode('\x19Ethereum Signed Message:\n');
66
+ const lengthBytes = new TextEncoder().encode(message.length.toString());
67
+ const combined = new Uint8Array(prefix.length + lengthBytes.length + message.length);
68
+ combined.set(prefix, 0);
69
+ combined.set(lengthBytes, prefix.length);
70
+ combined.set(message, prefix.length + lengthBytes.length);
71
+ return keccak_256(combined);
72
+ }
73
+
74
+ function ecrecover(msgHash: Uint8Array, v: bigint, r: Uint8Array, s: Uint8Array): Uint8Array {
75
+ const recovery = Number(v);
76
+ const signature = new Uint8Array(64);
77
+ signature.set(r, 0);
78
+ signature.set(s, 32);
79
+
80
+ const publicKey = secp256k1.Signature.fromBytes(signature)
81
+ .addRecoveryBit(recovery)
82
+ .recoverPublicKey(msgHash);
83
+
84
+ return publicKey.toBytes(false).slice(1); // Remove the 0x04 prefix for uncompressed key
85
+ }
86
+
87
+ function publicToAddress(publicKey: Uint8Array): Uint8Array {
88
+ const hash = keccak_256(publicKey);
89
+ return hash.slice(-20); // Take last 20 bytes
90
+ }
91
+
5
92
  export default async function verifyWeb3Address(
6
93
  root: never,
7
94
  { address, hash }: { address: string; hash: `0x${string}` },
@@ -11,6 +98,14 @@ export default async function verifyWeb3Address(
11
98
  userId,
12
99
  });
13
100
 
101
+ // Load noble packages dynamically
102
+ const packagesLoaded = await loadNoblePackages();
103
+ if (!packagesLoaded) {
104
+ throw new Error(
105
+ 'Web3 signature verification is not available. Please install the required @noble packages: @noble/curves, @noble/hashes',
106
+ );
107
+ }
108
+
14
109
  const foundCredentials = user.services?.web3?.find(
15
110
  (service) => service.address.toLowerCase() === address.toLowerCase(),
16
111
  );
@@ -20,17 +115,15 @@ export default async function verifyWeb3Address(
20
115
 
21
116
  // eslint-disable-next-line
22
117
  // @ts-ignore
23
- const { bufferToHex, fromRpcSig, ecrecover, toBuffer, hashPersonalMessage, publicToAddress } =
24
- await import('@ethereumjs/util');
25
-
26
- const message = `0x${Buffer.from(foundCredentials.nonce, 'utf8').toString('hex')}`;
27
- const messageHash = hashPersonalMessage(toBuffer(message));
118
+ const messageHash = hashPersonalMessage(
119
+ hexToBytes(`0x${Buffer.from(foundCredentials.nonce, 'utf8').toString('hex')}`),
120
+ );
28
121
 
29
- const sigParams = fromRpcSig(hash);
122
+ const sigParams = fromRPCSig(hash);
30
123
  const publicKey = ecrecover(messageHash, sigParams.v, sigParams.r, sigParams.s);
31
124
 
32
125
  const sender = publicToAddress(publicKey);
33
- const recoveredAddr = bufferToHex(sender);
126
+ const recoveredAddr = `0x${bytesToHex(sender)}`;
34
127
 
35
128
  const isSignatureCorrectForAddress =
36
129
  recoveredAddr.toLowerCase() === foundCredentials.address.toLowerCase();
@@ -138,7 +138,6 @@ import removePaymentCredentials from './payment/removePaymentCredentials.js';
138
138
  import updateOrderDeliveryShipping from './orders/updateOrderDeliveryShipping.js';
139
139
  import updateOrderDeliveryPickUp from './orders/updateOrderDeliveryPickUp.js';
140
140
  import updateOrderPaymentGeneric from './orders/updateOrderPaymentGeneric.js';
141
- import updateOrderPaymentCard from './orders/updateOrderPaymentCard.js';
142
141
  import updateOrderPaymentInvoice from './orders/updateOrderPaymentInvoice.js';
143
142
  import signPaymentProviderForCredentialRegistration from './payment/signPaymentProviderForCredentialRegistration.js';
144
143
  import signPaymentProviderForCheckout from './orders/signPaymentProviderForCheckout.js';
@@ -153,6 +152,10 @@ import rejectOrder from './orders/rejectOrder.js';
153
152
  import removePushSubscription from './users/removePushSubscription.js';
154
153
  import addPushSubscription from './users/addPushSubscription.js';
155
154
  import removeUserProductReviews from './users/removeUserProductReviews.js';
155
+ import updateCartDeliveryPickUp from './orders/updateCartDeliveryPickUp.js';
156
+ import updateCartDeliveryShipping from './orders/updateCartDeliveryShipping.js';
157
+ import updateCartPaymentGeneric from './orders/updateCartPaymentGeneric.js';
158
+ import updateCartPaymentInvoice from './orders/updateCartPaymentInvoice.js';
156
159
 
157
160
  export default {
158
161
  logout: acl(actions.logout)(logout),
@@ -244,12 +247,15 @@ export default {
244
247
  updateCartItem: acl(actions.updateOrderItem)(updateCartItem),
245
248
  removeCartItem: acl(actions.updateOrderItem)(removeCartItem),
246
249
  removeCartDiscount: acl(actions.updateOrderDiscount)(removeCartDiscount),
250
+ updateCartDeliveryPickUp: acl(actions.updateCart)(updateCartDeliveryPickUp),
251
+ updateCartDeliveryShipping: acl(actions.updateCart)(updateCartDeliveryShipping),
252
+ updateCartPaymentGeneric: acl(actions.updateCart)(updateCartPaymentGeneric),
253
+ updateCartPaymentInvoice: acl(actions.updateCart)(updateCartPaymentInvoice),
247
254
  setOrderPaymentProvider: acl(actions.updateOrder)(setOrderPaymentProvider),
248
255
  setOrderDeliveryProvider: acl(actions.updateOrder)(setOrderDeliveryProvider),
249
256
  updateOrderDeliveryShipping: acl(actions.updateOrderDelivery)(updateOrderDeliveryShipping),
250
257
  updateOrderDeliveryPickUp: acl(actions.updateOrderDelivery)(updateOrderDeliveryPickUp),
251
258
  updateOrderPaymentGeneric: acl(actions.updateOrderPayment)(updateOrderPaymentGeneric),
252
- updateOrderPaymentCard: acl(actions.updateOrderPayment)(updateOrderPaymentCard),
253
259
  updateOrderPaymentInvoice: acl(actions.updateOrderPayment)(updateOrderPaymentInvoice),
254
260
  removeOrder: acl(actions.updateOrder)(removeOrder),
255
261
  confirmOrder: acl(actions.markOrderConfirmed)(confirmOrder),
@@ -19,7 +19,7 @@ export default async function updateCart(root: never, params: UpdateCartParams,
19
19
 
20
20
  log('mutation updateCart', { userId });
21
21
 
22
- let order = await services.orders.findOrInitCart({
22
+ const order = await services.orders.findOrInitCart({
23
23
  orderId,
24
24
  user,
25
25
  countryCode: context.countryCode,
@@ -28,23 +28,23 @@ export default async function updateCart(root: never, params: UpdateCartParams,
28
28
  if (!modules.orders.isCart(order)) throw new OrderWrongStatusError({ status: order.status });
29
29
 
30
30
  if (meta) {
31
- order = await modules.orders.updateContext(order._id, meta);
31
+ await modules.orders.updateContext(order._id, meta);
32
32
  }
33
33
 
34
34
  if (billingAddress) {
35
- order = await modules.orders.updateBillingAddress(order._id, billingAddress);
35
+ await modules.orders.updateBillingAddress(order._id, billingAddress);
36
36
  }
37
37
 
38
38
  if (contact) {
39
- order = await modules.orders.updateContact(order._id, contact);
39
+ await modules.orders.updateContact(order._id, contact);
40
40
  }
41
41
 
42
42
  if (paymentProviderId) {
43
- order = await modules.orders.setPaymentProvider(order._id, paymentProviderId);
43
+ await modules.orders.setPaymentProvider(order._id, paymentProviderId);
44
44
  }
45
45
 
46
46
  if (deliveryProviderId) {
47
- order = await modules.orders.setDeliveryProvider(order._id, deliveryProviderId);
47
+ await modules.orders.setDeliveryProvider(order._id, deliveryProviderId);
48
48
  }
49
49
 
50
50
  // Recalculate, then return
@@ -0,0 +1,51 @@
1
+ import { Context } from '../../../context.js';
2
+ import { DeliveryProviderType } from '@unchainedshop/core-delivery';
3
+ import { log } from '@unchainedshop/logger';
4
+ import {
5
+ InvalidIdError,
6
+ OrderDeliveryTypeError,
7
+ OrderNotFoundError,
8
+ OrderWrongStatusError,
9
+ } from '../../../errors.js';
10
+
11
+ export default async function updateCartDeliveryPickUp(
12
+ root: never,
13
+ params: { orderId: string; deliveryProviderId: string; orderPickUpLocationId: string; meta: any },
14
+ context: Context,
15
+ ) {
16
+ const { modules, services, userId, user } = context;
17
+ const { orderId, deliveryProviderId, orderPickUpLocationId, meta } = params;
18
+ log(`mutation updateCartDeliveryPickUp provider ${deliveryProviderId}`, {
19
+ userId,
20
+ });
21
+
22
+ if (!deliveryProviderId) throw new InvalidIdError({ deliveryProviderId });
23
+
24
+ let order = await services.orders.findOrInitCart({
25
+ orderId,
26
+ user,
27
+ countryCode: context.countryCode,
28
+ });
29
+ if (!order) throw new OrderNotFoundError({ orderId });
30
+ if (!modules.orders.isCart(order)) throw new OrderWrongStatusError({ status: order.status });
31
+
32
+ const provider = await modules.delivery.findProvider({
33
+ deliveryProviderId,
34
+ });
35
+ const deliveryProviderType = provider?.type;
36
+
37
+ if (deliveryProviderType !== DeliveryProviderType.PICKUP)
38
+ throw new OrderDeliveryTypeError({
39
+ orderId: order._id,
40
+ received: deliveryProviderType,
41
+ required: DeliveryProviderType.PICKUP,
42
+ });
43
+
44
+ order = (await modules.orders.setDeliveryProvider(order._id, deliveryProviderId)) || order;
45
+
46
+ await modules.orders.deliveries.updateContext(order.deliveryId, {
47
+ orderPickUpLocationId,
48
+ meta,
49
+ });
50
+ return services.orders.updateCalculation(order._id);
51
+ }
@@ -0,0 +1,51 @@
1
+ import { Context } from '../../../context.js';
2
+ import { DeliveryProviderType } from '@unchainedshop/core-delivery';
3
+ import { log } from '@unchainedshop/logger';
4
+ import {
5
+ InvalidIdError,
6
+ OrderDeliveryTypeError,
7
+ OrderNotFoundError,
8
+ OrderWrongStatusError,
9
+ } from '../../../errors.js';
10
+
11
+ export default async function updateCartDeliveryShipping(
12
+ root: never,
13
+ params: { orderId: string; deliveryProviderId: string; address: any; meta: any },
14
+ context: Context,
15
+ ) {
16
+ const { modules, services, userId, user } = context;
17
+ const { orderId, deliveryProviderId, address, meta } = params;
18
+ log(`mutation updateCartDeliveryShipping provider ${deliveryProviderId}`, {
19
+ userId,
20
+ });
21
+
22
+ if (!deliveryProviderId) throw new InvalidIdError({ deliveryProviderId });
23
+
24
+ let order = await services.orders.findOrInitCart({
25
+ orderId,
26
+ user,
27
+ countryCode: context.countryCode,
28
+ });
29
+ if (!order) throw new OrderNotFoundError({ orderId });
30
+ if (!modules.orders.isCart(order)) throw new OrderWrongStatusError({ status: order.status });
31
+
32
+ const provider = await modules.delivery.findProvider({
33
+ deliveryProviderId,
34
+ });
35
+ const deliveryProviderType = provider?.type;
36
+
37
+ if (deliveryProviderType !== DeliveryProviderType.SHIPPING)
38
+ throw new OrderDeliveryTypeError({
39
+ orderId: order._id,
40
+ received: deliveryProviderType,
41
+ required: DeliveryProviderType.SHIPPING,
42
+ });
43
+
44
+ order = (await modules.orders.setDeliveryProvider(order._id, deliveryProviderId)) || order;
45
+
46
+ await modules.orders.deliveries.updateContext(order.deliveryId, {
47
+ address,
48
+ meta,
49
+ });
50
+ return services.orders.updateCalculation(order._id);
51
+ }
@@ -0,0 +1,50 @@
1
+ import { Context } from '../../../context.js';
2
+ import { PaymentProviderType } from '@unchainedshop/core-payment';
3
+ import { log } from '@unchainedshop/logger';
4
+ import {
5
+ InvalidIdError,
6
+ OrderNotFoundError,
7
+ OrderPaymentTypeError,
8
+ OrderWrongStatusError,
9
+ } from '../../../errors.js';
10
+
11
+ export default async function updateCartPaymentGeneric(
12
+ root: never,
13
+ params: { orderId: string; paymentProviderId: string; meta?: any },
14
+ context: Context,
15
+ ) {
16
+ const { modules, services, userId, user } = context;
17
+ const { orderId, paymentProviderId, meta } = params;
18
+ log(`mutation updateCartPaymentGeneric provider ${paymentProviderId}`, {
19
+ userId,
20
+ });
21
+
22
+ if (!paymentProviderId) throw new InvalidIdError({ paymentProviderId });
23
+
24
+ let order = await services.orders.findOrInitCart({
25
+ orderId,
26
+ user,
27
+ countryCode: context.countryCode,
28
+ });
29
+ if (!order) throw new OrderNotFoundError({ orderId });
30
+ if (!modules.orders.isCart(order)) throw new OrderWrongStatusError({ status: order.status });
31
+
32
+ const provider = await modules.payment.paymentProviders.findProvider({
33
+ paymentProviderId,
34
+ });
35
+ const paymentProviderType = provider?.type;
36
+
37
+ if (paymentProviderType !== PaymentProviderType.GENERIC)
38
+ throw new OrderPaymentTypeError({
39
+ orderId: order._id,
40
+ received: paymentProviderType,
41
+ required: PaymentProviderType.GENERIC,
42
+ });
43
+
44
+ order = (await modules.orders.setPaymentProvider(order._id, paymentProviderId)) || order;
45
+
46
+ await modules.orders.payments.updateContext(order.paymentId, {
47
+ meta,
48
+ });
49
+ return services.orders.updateCalculation(order._id);
50
+ }
@@ -0,0 +1,50 @@
1
+ import { Context } from '../../../context.js';
2
+ import { PaymentProviderType } from '@unchainedshop/core-payment';
3
+ import { log } from '@unchainedshop/logger';
4
+ import {
5
+ InvalidIdError,
6
+ OrderNotFoundError,
7
+ OrderPaymentTypeError,
8
+ OrderWrongStatusError,
9
+ } from '../../../errors.js';
10
+
11
+ export default async function updateCartPaymentInvoice(
12
+ root: never,
13
+ params: { orderId: string; paymentProviderId: string; meta?: any },
14
+ context: Context,
15
+ ) {
16
+ const { modules, services, userId, user } = context;
17
+ const { orderId, paymentProviderId, meta } = params;
18
+ log(`mutation updateCartPaymentInvoice provider ${paymentProviderId}`, {
19
+ userId,
20
+ });
21
+
22
+ if (!paymentProviderId) throw new InvalidIdError({ paymentProviderId });
23
+
24
+ let order = await services.orders.findOrInitCart({
25
+ orderId,
26
+ user,
27
+ countryCode: context.countryCode,
28
+ });
29
+ if (!order) throw new OrderNotFoundError({ orderId });
30
+ if (!modules.orders.isCart(order)) throw new OrderWrongStatusError({ status: order.status });
31
+
32
+ const provider = await modules.payment.paymentProviders.findProvider({
33
+ paymentProviderId,
34
+ });
35
+ const paymentProviderType = provider?.type;
36
+
37
+ if (paymentProviderType !== PaymentProviderType.INVOICE)
38
+ throw new OrderPaymentTypeError({
39
+ orderId: order._id,
40
+ received: paymentProviderType,
41
+ required: PaymentProviderType.INVOICE,
42
+ });
43
+
44
+ order = (await modules.orders.setPaymentProvider(order._id, paymentProviderId)) || order;
45
+
46
+ await modules.orders.payments.updateContext(order.paymentId, {
47
+ meta,
48
+ });
49
+ return services.orders.updateCalculation(order._id);
50
+ }
@@ -1,6 +1,6 @@
1
1
  import { log } from '@unchainedshop/logger';
2
- import { ProductCommerce } from '@unchainedshop/core-products';
3
- import { ProductNotFoundError, InvalidIdError } from '../../../errors.js';
2
+ import { ProductCommerce, ProductTypes } from '@unchainedshop/core-products';
3
+ import { ProductNotFoundError, InvalidIdError, ProductWrongTypeError } from '../../../errors.js';
4
4
  import { Context } from '../../../context.js';
5
5
 
6
6
  export default async function updateProductCommerce(
@@ -12,8 +12,16 @@ export default async function updateProductCommerce(
12
12
 
13
13
  if (!productId) throw new InvalidIdError({ productId });
14
14
 
15
- if (!(await modules.products.productExists({ productId })))
16
- throw new ProductNotFoundError({ productId });
15
+ const product = await modules.products.findProduct({ productId });
16
+ if (!product) throw new ProductNotFoundError({ productId });
17
+
18
+ if (product.type === ProductTypes.ConfigurableProduct) {
19
+ throw new ProductWrongTypeError({
20
+ productId: productId,
21
+ received: product.type,
22
+ required: { not: ProductTypes.ConfigurableProduct },
23
+ });
24
+ }
17
25
 
18
26
  await modules.products.update(productId, { commerce });
19
27
 
@@ -5,12 +5,12 @@ import { DateFilterInput } from '@unchainedshop/utils';
5
5
  export default async function orderStatistics(
6
6
  root: never,
7
7
  params: { dateRange?: DateFilterInput },
8
- { modules, userId }: Context,
8
+ { userId }: Context,
9
9
  ) {
10
+ const { dateRange } = params || {};
10
11
  log(`query orderStatistics `, {
11
12
  userId,
12
13
  ...(params?.dateRange || {}),
13
14
  });
14
-
15
- return modules.orders.getReport(params);
15
+ return { dateRange };
16
16
  }
@@ -67,6 +67,7 @@ import { Token } from './token-types.js';
67
67
  import { Web3Address } from './web3-address.js';
68
68
  import { LoginMethodResponse } from './login-method-response-types.js';
69
69
  import { ProductSearchResult } from './product-search-result-types.js';
70
+ import { OrderStatistics } from './order/order-statistics-types.js';
70
71
 
71
72
  const types = {
72
73
  Assortment,
@@ -138,6 +139,7 @@ const types = {
138
139
  Media,
139
140
  Web3Address,
140
141
  LoginMethodResponse,
142
+ OrderStatistics,
141
143
  };
142
144
 
143
145
  export default types;