@unchainedshop/api 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.
Files changed (168) hide show
  1. package/README.md +204 -0
  2. package/lib/api-index.js +3 -0
  3. package/lib/chat/generateImageHandler.d.ts +7 -1
  4. package/lib/chat/generateImageHandler.js +4 -5
  5. package/lib/context.js +2 -13
  6. package/lib/errors.d.ts +1 -0
  7. package/lib/errors.js +2 -1
  8. package/lib/events.js +0 -2
  9. package/lib/express/chatHandler.js +4 -4
  10. package/lib/express/createERCMetadataMiddleware.js +1 -1
  11. package/lib/express/index.js +23 -9
  12. package/lib/fastify/chatHandler.js +4 -4
  13. package/lib/fastify/ercMetadataHandler.js +1 -1
  14. package/lib/fastify/index.js +9 -3
  15. package/lib/loaders/assortmentMediaTextLoader.js +1 -1
  16. package/lib/loaders/assortmentMediasLoader.js +1 -1
  17. package/lib/loaders/assortmentTextLoader.js +1 -1
  18. package/lib/loaders/countryLoader.js +1 -1
  19. package/lib/loaders/currencyLoader.js +1 -1
  20. package/lib/loaders/deliveryProviderLoader.js +1 -1
  21. package/lib/loaders/fileLoader.js +1 -1
  22. package/lib/loaders/filterTextLoader.js +1 -1
  23. package/lib/loaders/languageLoader.js +1 -1
  24. package/lib/loaders/orderLoader.js +1 -1
  25. package/lib/loaders/paymentProviderLoader.js +1 -1
  26. package/lib/loaders/productBySKULoader.js +2 -4
  27. package/lib/loaders/productLoader.js +1 -3
  28. package/lib/loaders/productMediaTextLoader.js +1 -1
  29. package/lib/loaders/productMediasLoader.js +1 -1
  30. package/lib/loaders/productProxiesLoader.js +2 -10
  31. package/lib/loaders/productTextLoader.js +1 -1
  32. package/lib/loaders/productVariationByKeyLoader.js +1 -1
  33. package/lib/loaders/productVariationLoader.js +1 -1
  34. package/lib/loaders/productVariationTextLoader.js +1 -1
  35. package/lib/loaders/quotationLoader.js +1 -1
  36. package/lib/loaders/userLoader.js +1 -1
  37. package/lib/loaders/warehousingProviderLoader.js +1 -1
  38. package/lib/mcp/tools/assortment/handlers/addAssortmentFilter.d.ts +0 -1
  39. package/lib/mcp/tools/assortment/handlers/addAssortmentLink.d.ts +0 -1
  40. package/lib/mcp/tools/assortment/handlers/addAssortmentMedia.d.ts +0 -1
  41. package/lib/mcp/tools/assortment/handlers/addAssortmentProduct.d.ts +0 -1
  42. package/lib/mcp/tools/assortment/handlers/createAssortment.d.ts +0 -1
  43. package/lib/mcp/tools/assortment/handlers/getAssortment.d.ts +0 -1
  44. package/lib/mcp/tools/assortment/handlers/getAssortmentChildren.d.ts +0 -2
  45. package/lib/mcp/tools/assortment/handlers/getAssortmentFilters.d.ts +0 -1
  46. package/lib/mcp/tools/assortment/handlers/getAssortmentLinks.d.ts +0 -2
  47. package/lib/mcp/tools/assortment/handlers/getAssortmentMedia.d.ts +0 -1
  48. package/lib/mcp/tools/assortment/handlers/getAssortmentProducts.d.ts +0 -1
  49. package/lib/mcp/tools/assortment/handlers/index.d.ts +0 -2
  50. package/lib/mcp/tools/assortment/handlers/index.js +0 -2
  51. package/lib/mcp/tools/assortment/handlers/listAssortments.d.ts +0 -1
  52. package/lib/mcp/tools/assortment/handlers/reorderAssortmentLinks.d.ts +0 -1
  53. package/lib/mcp/tools/assortment/handlers/searchAssortmentProducts.d.ts +0 -1
  54. package/lib/mcp/tools/assortment/handlers/updateAssortment.d.ts +0 -1
  55. package/lib/mcp/tools/assortment/handlers/updateAssortmentStatus.d.ts +0 -1
  56. package/lib/mcp/tools/assortment/schemas.d.ts +0 -5
  57. package/lib/mcp/tools/assortment/schemas.js +0 -4
  58. package/lib/mcp/tools/order/handlers/confirmOrder.d.ts +1 -1
  59. package/lib/mcp/tools/order/handlers/deliverOrder.d.ts +1 -1
  60. package/lib/mcp/tools/order/handlers/getOrder.d.ts +1 -1
  61. package/lib/mcp/tools/order/handlers/getTopCustomers.d.ts +6 -6
  62. package/lib/mcp/tools/order/handlers/getTopCustomers.js +5 -55
  63. package/lib/mcp/tools/order/handlers/getTopProducts.d.ts +3 -3
  64. package/lib/mcp/tools/order/handlers/getTopProducts.js +4 -43
  65. package/lib/mcp/tools/order/handlers/getUserCart.d.ts +1 -1
  66. package/lib/mcp/tools/order/handlers/listOrders.d.ts +1 -1
  67. package/lib/mcp/tools/order/handlers/payOrder.d.ts +1 -1
  68. package/lib/mcp/tools/order/handlers/rejectOrder.d.ts +1 -1
  69. package/lib/mcp/tools/provider/handlers/listProviders.js +4 -8
  70. package/lib/mcp/tools/quotation/handlers/getQuotation.d.ts +2 -2
  71. package/lib/mcp/tools/quotation/handlers/listQuotations.d.ts +2 -2
  72. package/lib/mcp/tools/quotation/handlers/makeQuotationProposal.d.ts +2 -2
  73. package/lib/mcp/tools/quotation/handlers/rejectQuotation.d.ts +2 -2
  74. package/lib/mcp/tools/quotation/handlers/rejectQuotation.js +1 -1
  75. package/lib/mcp/tools/quotation/handlers/verifyQuotation.d.ts +2 -2
  76. package/lib/mcp/tools/quotation/index.js +1 -1
  77. package/lib/mcp/tools/quotation/schemas.d.ts +5 -5
  78. package/lib/mcp/tools/quotation/schemas.js +3 -3
  79. package/lib/mcp/tools/system/schemas.d.ts +6 -6
  80. package/lib/mcp/tools/system/schemas.js +14 -7
  81. package/lib/mcp/tools/users/handlers/addUserEmail.d.ts +1 -1
  82. package/lib/mcp/tools/users/handlers/createUser.d.ts +1 -1
  83. package/lib/mcp/tools/users/handlers/enrollUser.d.ts +1 -1
  84. package/lib/mcp/tools/users/handlers/getCurrentUser.d.ts +1 -1
  85. package/lib/mcp/tools/users/handlers/getUser.d.ts +1 -1
  86. package/lib/mcp/tools/users/handlers/getUserOrders.d.ts +1 -1
  87. package/lib/mcp/tools/users/handlers/getUserQuotations.d.ts +1 -1
  88. package/lib/mcp/tools/users/handlers/listUsers.d.ts +1 -1
  89. package/lib/mcp/tools/users/handlers/setUserTags.d.ts +1 -1
  90. package/lib/mcp/tools/users/handlers/setUserUsername.d.ts +1 -1
  91. package/lib/mcp/tools/users/handlers/updateUser.d.ts +1 -1
  92. package/lib/mcp/utils/getNormalizedAssortmentDetails.d.ts +0 -1
  93. package/lib/mcp/utils/getNormalizedOrderDetails.d.ts +1 -1
  94. package/lib/mcp/utils/getNormalizedQuotationDetails.d.ts +2 -2
  95. package/lib/mcp/utils/getNormalizedUserDetails.d.ts +1 -1
  96. package/lib/mongo-store.d.ts +9 -5
  97. package/lib/mongo-store.js +31 -25
  98. package/lib/resolvers/mutations/accounts/addWeb3Address.d.ts +2 -2
  99. package/lib/resolvers/mutations/accounts/addWeb3Address.js +1 -14
  100. package/lib/resolvers/mutations/accounts/addWebAuthnCredentials.d.ts +2 -2
  101. package/lib/resolvers/mutations/accounts/addWebAuthnCredentials.js +2 -6
  102. package/lib/resolvers/mutations/accounts/createUser.js +3 -1
  103. package/lib/resolvers/mutations/accounts/createWebAuthnCredentialCreationOptions.d.ts +1 -4
  104. package/lib/resolvers/mutations/accounts/createWebAuthnCredentialRequestOptions.d.ts +1 -4
  105. package/lib/resolvers/mutations/accounts/forgotPassword.js +4 -4
  106. package/lib/resolvers/mutations/accounts/loginAsGuest.js +1 -3
  107. package/lib/resolvers/mutations/accounts/removeWeb3Address.d.ts +1 -1
  108. package/lib/resolvers/mutations/accounts/removeWeb3Address.js +3 -7
  109. package/lib/resolvers/mutations/accounts/removeWebAuthnCredentials.d.ts +1 -1
  110. package/lib/resolvers/mutations/accounts/removeWebAuthnCredentials.js +1 -5
  111. package/lib/resolvers/mutations/accounts/verifyWeb3Address.d.ts +2 -2
  112. package/lib/resolvers/mutations/accounts/verifyWeb3Address.js +8 -89
  113. package/lib/resolvers/mutations/filters/removeFilter.d.ts +2 -2
  114. package/lib/resolvers/mutations/filters/removeFilter.js +3 -5
  115. package/lib/resolvers/mutations/index.d.ts +0 -1
  116. package/lib/resolvers/mutations/index.js +0 -2
  117. package/lib/resolvers/mutations/orders/addMultipleCartProducts.js +23 -31
  118. package/lib/resolvers/mutations/orders/removeCartDiscount.d.ts +2 -2
  119. package/lib/resolvers/mutations/orders/removeCartDiscount.js +9 -14
  120. package/lib/resolvers/mutations/orders/updateCart.js +2 -8
  121. package/lib/resolvers/mutations/quotations/rejectQuotation.js +1 -1
  122. package/lib/resolvers/mutations/users/removeUser.d.ts +1 -1
  123. package/lib/resolvers/mutations/users/removeUser.js +2 -3
  124. package/lib/resolvers/mutations/warehousing/exportToken.js +9 -17
  125. package/lib/resolvers/queries/payment/paymentProvidersCount.d.ts +3 -3
  126. package/lib/resolvers/queries/payment/paymentProvidersCount.js +1 -1
  127. package/lib/resolvers/queries/shopInfo.js +4 -36
  128. package/lib/resolvers/type/delivery-provider-interface.d.ts +1 -7
  129. package/lib/resolvers/type/delivery-provider-interface.js +10 -20
  130. package/lib/resolvers/type/delivery-provider-pickup-types.d.ts +1 -7
  131. package/lib/resolvers/type/delivery-provider-shipping-types.d.ts +1 -7
  132. package/lib/resolvers/type/delivery-provider-types.d.ts +1 -7
  133. package/lib/resolvers/type/index.d.ts +33 -54
  134. package/lib/resolvers/type/media-types.d.ts +1 -1
  135. package/lib/resolvers/type/media-types.js +7 -5
  136. package/lib/resolvers/type/order/order-item-types.d.ts +2 -9
  137. package/lib/resolvers/type/order/order-item-types.js +2 -37
  138. package/lib/resolvers/type/order/order-statistics-types.d.ts +10 -10
  139. package/lib/resolvers/type/order/order-statistics-types.js +10 -64
  140. package/lib/resolvers/type/payment/payment-provider-types.d.ts +1 -7
  141. package/lib/resolvers/type/payment/payment-provider-types.js +7 -17
  142. package/lib/resolvers/type/price-types.d.ts +0 -1
  143. package/lib/resolvers/type/product/product-bundle-types.d.ts +1 -1
  144. package/lib/resolvers/type/product/product-configurable-types.d.ts +1 -1
  145. package/lib/resolvers/type/product/product-configurable-types.js +9 -32
  146. package/lib/resolvers/type/product/product-plan-types.d.ts +1 -1
  147. package/lib/resolvers/type/product/product-simple-types.d.ts +1 -1
  148. package/lib/resolvers/type/product/product-tokenized-types.d.ts +1 -1
  149. package/lib/resolvers/type/product/product-types.d.ts +1 -1
  150. package/lib/resolvers/type/product/product-types.js +7 -17
  151. package/lib/resolvers/type/shop-types.js +2 -5
  152. package/lib/resolvers/type/token-types.d.ts +3 -3
  153. package/lib/resolvers/type/token-types.js +4 -25
  154. package/lib/resolvers/type/user-types.js +1 -4
  155. package/lib/resolvers/type/webauthn-credentials-types.d.ts +10 -1
  156. package/lib/roles/index.d.ts +2 -1
  157. package/lib/roles/index.js +7 -1
  158. package/lib/schema/mutation.js +1 -7
  159. package/lib/schema/types/assortment.js +0 -1
  160. package/lib/schema/types/order/order.js +2 -2
  161. package/lib/schema/types/quotation.js +2 -2
  162. package/lib/utils/getConfiguredTags.d.ts +1 -0
  163. package/lib/utils/getConfiguredTags.js +9 -0
  164. package/package.json +14 -23
  165. package/lib/mcp/tools/assortment/handlers/setAssortmentBase.d.ts +0 -28
  166. package/lib/mcp/tools/assortment/handlers/setAssortmentBase.js +0 -11
  167. package/lib/resolvers/mutations/assortments/setBaseAssortment.d.ts +0 -4
  168. package/lib/resolvers/mutations/assortments/setBaseAssortment.js +0 -11
@@ -10,7 +10,7 @@ export default function getQuotation(context: Context, params: Params<'GET'>): P
10
10
  mediaId: string;
11
11
  } | null)[] | null;
12
12
  _id: string;
13
- deleted?: Date;
13
+ deleted?: Date | null;
14
14
  avatarId?: string;
15
15
  emails: import("@unchainedshop/core-users").Email[];
16
16
  guest: boolean;
@@ -82,7 +82,7 @@ export default function getQuotation(context: Context, params: Params<'GET'>): P
82
82
  countryCode?: string;
83
83
  currencyCode?: string;
84
84
  expires?: Date;
85
- fullfilled?: Date;
85
+ fulfilled?: Date;
86
86
  meta?: any;
87
87
  price?: number;
88
88
  productId: string;
@@ -11,7 +11,7 @@ export default function listQuotations(context: Context, params: Params<'LIST'>)
11
11
  mediaId: string;
12
12
  } | null)[] | null;
13
13
  _id: string;
14
- deleted?: Date;
14
+ deleted?: Date | null;
15
15
  avatarId?: string;
16
16
  emails: import("@unchainedshop/core-users").Email[];
17
17
  guest: boolean;
@@ -83,7 +83,7 @@ export default function listQuotations(context: Context, params: Params<'LIST'>)
83
83
  countryCode?: string;
84
84
  currencyCode?: string;
85
85
  expires?: Date;
86
- fullfilled?: Date;
86
+ fulfilled?: Date;
87
87
  meta?: any;
88
88
  price?: number;
89
89
  productId: string;
@@ -11,7 +11,7 @@ export default function makeQuotationProposal(context: Context, params: Params<'
11
11
  mediaId: string;
12
12
  } | null)[] | null;
13
13
  _id: string;
14
- deleted?: Date;
14
+ deleted?: Date | null;
15
15
  avatarId?: string;
16
16
  emails: import("@unchainedshop/core-users").Email[];
17
17
  guest: boolean;
@@ -83,7 +83,7 @@ export default function makeQuotationProposal(context: Context, params: Params<'
83
83
  countryCode?: string;
84
84
  currencyCode?: string;
85
85
  expires?: Date;
86
- fullfilled?: Date;
86
+ fulfilled?: Date;
87
87
  meta?: any;
88
88
  price?: number;
89
89
  productId: string;
@@ -11,7 +11,7 @@ export default function rejectQuotation(context: Context, params: Params<'REJECT
11
11
  mediaId: string;
12
12
  } | null)[] | null;
13
13
  _id: string;
14
- deleted?: Date;
14
+ deleted?: Date | null;
15
15
  avatarId?: string;
16
16
  emails: import("@unchainedshop/core-users").Email[];
17
17
  guest: boolean;
@@ -83,7 +83,7 @@ export default function rejectQuotation(context: Context, params: Params<'REJECT
83
83
  countryCode?: string;
84
84
  currencyCode?: string;
85
85
  expires?: Date;
86
- fullfilled?: Date;
86
+ fulfilled?: Date;
87
87
  meta?: any;
88
88
  price?: number;
89
89
  productId: string;
@@ -7,7 +7,7 @@ export default async function rejectQuotation(context, params) {
7
7
  const quotation = await modules.quotations.findQuotation({ quotationId });
8
8
  if (!quotation)
9
9
  throw new QuotationNotFoundError({ quotationId });
10
- if (quotation.status === QuotationStatus.FULLFILLED) {
10
+ if (quotation.status === QuotationStatus.FULFILLED) {
11
11
  throw new QuotationWrongStatusError({ status: quotation.status });
12
12
  }
13
13
  const rejectedQuotation = await services.quotations.rejectQuotation(quotation, quotationContext || {});
@@ -11,7 +11,7 @@ export default function verifyQuotation(context: Context, params: Params<'VERIFY
11
11
  mediaId: string;
12
12
  } | null)[] | null;
13
13
  _id: string;
14
- deleted?: Date;
14
+ deleted?: Date | null;
15
15
  avatarId?: string;
16
16
  emails: import("@unchainedshop/core-users").Email[];
17
17
  guest: boolean;
@@ -83,7 +83,7 @@ export default function verifyQuotation(context: Context, params: Params<'VERIFY
83
83
  countryCode?: string;
84
84
  currencyCode?: string;
85
85
  expires?: Date;
86
- fullfilled?: Date;
86
+ fulfilled?: Date;
87
87
  meta?: any;
88
88
  price?: number;
89
89
  productId: string;
@@ -1,4 +1,4 @@
1
1
  import { quotationManagement, QuotationManagementSchema } from "./quotationManagement.js";
2
2
  export const registerQuotationTools = (server, context) => {
3
- server.tool('quotation_management', 'Unified quotation management system. Supports: LIST (get quotations with filters and pagination), GET (single quotation by ID), COUNT (count quotations), REQUEST (create new quotation request for a product), VERIFY (verify a REQUESTED quotation), MAKE_PROPOSAL (create proposal for PROCESSING quotation), REJECT (reject any quotation except FULLFILLED). Quotations go through lifecycle: REQUESTED → PROCESSING → PROPOSED → FULLFILLED/REJECTED.', QuotationManagementSchema, async (params) => quotationManagement(context, params));
3
+ server.tool('quotation_management', 'Unified quotation management system. Supports: LIST (get quotations with filters and pagination), GET (single quotation by ID), COUNT (count quotations), REQUEST (create new quotation request for a product), VERIFY (verify a REQUESTED quotation), MAKE_PROPOSAL (create proposal for PROCESSING quotation), REJECT (reject any quotation except FULFILLED). Quotations go through lifecycle: REQUESTED → PROCESSING → PROPOSED → FULFILLED/REJECTED.', QuotationManagementSchema, async (params) => quotationManagement(context, params));
4
4
  };
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  export declare const QuotationStatusEnum: z.ZodEnum<{
3
- FULLFILLED: "FULLFILLED";
3
+ FULFILLED: "FULFILLED";
4
4
  REJECTED: "REJECTED";
5
5
  REQUESTED: "REQUESTED";
6
6
  PROCESSING: "PROCESSING";
@@ -13,7 +13,7 @@ export declare const ProductConfigurationInput: z.ZodObject<{
13
13
  export declare const actionValidators: {
14
14
  readonly LIST: z.ZodObject<{
15
15
  status: z.ZodOptional<z.ZodEnum<{
16
- FULLFILLED: "FULLFILLED";
16
+ FULFILLED: "FULFILLED";
17
17
  REJECTED: "REJECTED";
18
18
  REQUESTED: "REQUESTED";
19
19
  PROCESSING: "PROCESSING";
@@ -39,7 +39,7 @@ export declare const actionValidators: {
39
39
  }, z.core.$strip>;
40
40
  readonly COUNT: z.ZodObject<{
41
41
  status: z.ZodOptional<z.ZodEnum<{
42
- FULLFILLED: "FULLFILLED";
42
+ FULFILLED: "FULFILLED";
43
43
  REJECTED: "REJECTED";
44
44
  REQUESTED: "REQUESTED";
45
45
  PROCESSING: "PROCESSING";
@@ -67,7 +67,7 @@ export declare const actionValidators: {
67
67
  };
68
68
  export declare const QuotationManagementSchema: {
69
69
  status: z.ZodOptional<z.ZodEnum<{
70
- FULLFILLED: "FULLFILLED";
70
+ FULFILLED: "FULFILLED";
71
71
  REJECTED: "REJECTED";
72
72
  REQUESTED: "REQUESTED";
73
73
  PROCESSING: "PROCESSING";
@@ -104,7 +104,7 @@ export declare const QuotationManagementSchema: {
104
104
  };
105
105
  export declare const QuotationManagementZodSchema: z.ZodObject<{
106
106
  status: z.ZodOptional<z.ZodEnum<{
107
- FULLFILLED: "FULLFILLED";
107
+ FULFILLED: "FULFILLED";
108
108
  REJECTED: "REJECTED";
109
109
  REQUESTED: "REQUESTED";
110
110
  PROCESSING: "PROCESSING";
@@ -4,7 +4,7 @@ export const QuotationStatusEnum = z.enum([
4
4
  'REQUESTED',
5
5
  'PROCESSING',
6
6
  'PROPOSED',
7
- 'FULLFILLED',
7
+ 'FULFILLED',
8
8
  'REJECTED',
9
9
  ]);
10
10
  export const ProductConfigurationInput = z.object({
@@ -66,13 +66,13 @@ export const actionValidators = {
66
66
  quotationId: z
67
67
  .string()
68
68
  .min(1, 'quotationId is required')
69
- .describe('Quotation ID to reject. Cannot be FULLFILLED.'),
69
+ .describe('Quotation ID to reject. Cannot be FULFILLED.'),
70
70
  quotationContext: z
71
71
  .record(z.any(), z.any())
72
72
  .optional()
73
73
  .describe('Optional context for rejection (e.g., reason for rejection, alternative suggestions)'),
74
74
  })
75
- .describe('Rejects a quotation and transitions it to REJECTED status. Requirements: quotation must exist AND current status must NOT be FULLFILLED (cannot reject completed quotations). Sets rejected timestamp.'),
75
+ .describe('Rejects a quotation and transitions it to REJECTED status. Requirements: quotation must exist AND current status must NOT be FULFILLED (cannot reject completed quotations). Sets rejected timestamp.'),
76
76
  };
77
77
  export const QuotationManagementSchema = {
78
78
  action: z
@@ -61,8 +61,8 @@ export declare const actionValidators: {
61
61
  error: z.ZodOptional<z.ZodAny>;
62
62
  success: z.ZodBoolean;
63
63
  worker: z.ZodOptional<z.ZodString>;
64
- started: z.ZodOptional<z.ZodDate>;
65
- finished: z.ZodOptional<z.ZodDate>;
64
+ started: z.ZodOptional<z.ZodString>;
65
+ finished: z.ZodOptional<z.ZodString>;
66
66
  }, z.core.$strip>;
67
67
  readonly WORKER_PROCESS_NEXT: z.ZodObject<{
68
68
  worker: z.ZodOptional<z.ZodString>;
@@ -151,8 +151,8 @@ export declare const SystemManagementSchema: {
151
151
  worker: z.ZodOptional<z.ZodString>;
152
152
  workId: z.ZodOptional<z.ZodString>;
153
153
  success: z.ZodOptional<z.ZodBoolean>;
154
- started: z.ZodOptional<z.ZodDate>;
155
- finished: z.ZodOptional<z.ZodDate>;
154
+ started: z.ZodOptional<z.ZodString>;
155
+ finished: z.ZodOptional<z.ZodString>;
156
156
  status: z.ZodOptional<z.ZodArray<z.ZodEnum<{
157
157
  [x: string]: string;
158
158
  }>>>;
@@ -200,8 +200,8 @@ export declare const SystemManagementZodSchema: z.ZodObject<{
200
200
  worker: z.ZodOptional<z.ZodString>;
201
201
  workId: z.ZodOptional<z.ZodString>;
202
202
  success: z.ZodOptional<z.ZodBoolean>;
203
- started: z.ZodOptional<z.ZodDate>;
204
- finished: z.ZodOptional<z.ZodDate>;
203
+ started: z.ZodOptional<z.ZodString>;
204
+ finished: z.ZodOptional<z.ZodString>;
205
205
  status: z.ZodOptional<z.ZodArray<z.ZodEnum<{
206
206
  [x: string]: string;
207
207
  }>>>;
@@ -105,11 +105,16 @@ export const actionValidators = {
105
105
  .string()
106
106
  .optional()
107
107
  .describe('Identifier of the worker that completed the task. Used for logging and tracking purposes.'),
108
- started: z.date().optional().describe('Timestamp when the worker began executing this work item.'),
108
+ started: z
109
+ .string()
110
+ .datetime()
111
+ .optional()
112
+ .describe('ISO 8601 timestamp when the worker began executing this work item.'),
109
113
  finished: z
110
- .date()
114
+ .string()
115
+ .datetime()
111
116
  .optional()
112
- .describe('Timestamp when the work execution completed (success or failure).'),
117
+ .describe('ISO 8601 timestamp when the work execution completed (success or failure).'),
113
118
  }),
114
119
  WORKER_PROCESS_NEXT: z.object({
115
120
  worker: z
@@ -219,13 +224,15 @@ export const SystemManagementSchema = {
219
224
  .optional()
220
225
  .describe('Success status for WORKER_FINISH_WORK action. Required to mark work as finished.'),
221
226
  started: z
222
- .date()
227
+ .string()
228
+ .datetime()
223
229
  .optional()
224
- .describe('Start timestamp for WORKER_FINISH_WORK action. When worker began execution.'),
230
+ .describe('ISO 8601 start timestamp for WORKER_FINISH_WORK action. When worker began execution.'),
225
231
  finished: z
226
- .date()
232
+ .string()
233
+ .datetime()
227
234
  .optional()
228
- .describe('Finish timestamp for WORKER_FINISH_WORK action. When work completed.'),
235
+ .describe('ISO 8601 finish timestamp for WORKER_FINISH_WORK action. When work completed.'),
229
236
  status: z
230
237
  .array(z.enum(WorkStatusKeys))
231
238
  .optional()
@@ -22,7 +22,7 @@ export default function addUserEmail(context: Context, params: Params<'ADD_EMAIL
22
22
  web3Addresses: any;
23
23
  reviews: import("@unchainedshop/core-products").ProductReview[];
24
24
  _id: string;
25
- deleted?: Date;
25
+ deleted?: Date | null;
26
26
  avatarId?: string;
27
27
  emails: import("@unchainedshop/core-users").Email[];
28
28
  guest: boolean;
@@ -22,7 +22,7 @@ export default function createUser(context: Context, params: Params<'CREATE'>):
22
22
  web3Addresses: any;
23
23
  reviews: import("@unchainedshop/core-products").ProductReview[];
24
24
  _id: string;
25
- deleted?: Date;
25
+ deleted?: Date | null;
26
26
  avatarId?: string;
27
27
  emails: import("@unchainedshop/core-users").Email[];
28
28
  guest: boolean;
@@ -22,7 +22,7 @@ export default function enrollUser(context: Context, params: Params<'ENROLL'>):
22
22
  web3Addresses: any;
23
23
  reviews: import("@unchainedshop/core-products").ProductReview[];
24
24
  _id: string;
25
- deleted?: Date;
25
+ deleted?: Date | null;
26
26
  avatarId?: string;
27
27
  emails: import("@unchainedshop/core-users").Email[];
28
28
  guest: boolean;
@@ -21,7 +21,7 @@ export default function getCurrentUser(context: Context): Promise<{
21
21
  web3Addresses: any;
22
22
  reviews: import("@unchainedshop/core-products").ProductReview[];
23
23
  _id: string;
24
- deleted?: Date;
24
+ deleted?: Date | null;
25
25
  avatarId?: string;
26
26
  emails: import("@unchainedshop/core-users").Email[];
27
27
  guest: boolean;
@@ -22,7 +22,7 @@ export default function getUser(context: Context, params: Params<'GET'>): Promis
22
22
  web3Addresses: any;
23
23
  reviews: import("@unchainedshop/core-products").ProductReview[];
24
24
  _id: string;
25
- deleted?: Date;
25
+ deleted?: Date | null;
26
26
  avatarId?: string;
27
27
  emails: import("@unchainedshop/core-users").Email[];
28
28
  guest: boolean;
@@ -76,7 +76,7 @@ export default function getUserOrders(context: Context, params: Params<'GET_ORDE
76
76
  countryCode: string;
77
77
  currencyCode: string;
78
78
  deliveryId?: string;
79
- fullfilled?: Date;
79
+ fulfilled?: Date;
80
80
  ordered?: Date;
81
81
  orderNumber?: string;
82
82
  originEnrollmentId?: string;
@@ -11,7 +11,7 @@ export default function getUserQuotations(context: Context, params: Params<'GET_
11
11
  countryCode?: string;
12
12
  currencyCode?: string;
13
13
  expires?: Date;
14
- fullfilled?: Date;
14
+ fulfilled?: Date;
15
15
  meta?: any;
16
16
  price?: number;
17
17
  quotationNumber?: string;
@@ -22,7 +22,7 @@ export default function listUsers(context: Context, params: Params<'LIST'>): Pro
22
22
  web3Addresses: any;
23
23
  reviews: import("@unchainedshop/core-products").ProductReview[];
24
24
  _id: string;
25
- deleted?: Date;
25
+ deleted?: Date | null;
26
26
  avatarId?: string;
27
27
  emails: import("@unchainedshop/core-users").Email[];
28
28
  guest: boolean;
@@ -22,7 +22,7 @@ export default function setUserTags(context: Context, params: Params<'SET_TAGS'>
22
22
  web3Addresses: any;
23
23
  reviews: import("@unchainedshop/core-products").ProductReview[];
24
24
  _id: string;
25
- deleted?: Date;
25
+ deleted?: Date | null;
26
26
  avatarId?: string;
27
27
  emails: import("@unchainedshop/core-users").Email[];
28
28
  guest: boolean;
@@ -22,7 +22,7 @@ export default function setUserUsername(context: Context, params: Params<'SET_US
22
22
  web3Addresses: any;
23
23
  reviews: import("@unchainedshop/core-products").ProductReview[];
24
24
  _id: string;
25
- deleted?: Date;
25
+ deleted?: Date | null;
26
26
  avatarId?: string;
27
27
  emails: import("@unchainedshop/core-users").Email[];
28
28
  guest: boolean;
@@ -22,7 +22,7 @@ export default function updateUser(context: Context, params: Params<'UPDATE'>):
22
22
  web3Addresses: any;
23
23
  reviews: import("@unchainedshop/core-products").ProductReview[];
24
24
  _id: string;
25
- deleted?: Date;
25
+ deleted?: Date | null;
26
26
  avatarId?: string;
27
27
  emails: import("@unchainedshop/core-users").Email[];
28
28
  guest: boolean;
@@ -15,7 +15,6 @@ export declare function getNormalizedAssortmentDetails({ assortmentId, slug }: {
15
15
  links: import("@unchainedshop/core-assortments").AssortmentLink[];
16
16
  products: import("@unchainedshop/core-assortments").AssortmentProduct[];
17
17
  isActive: boolean;
18
- isBase: boolean;
19
18
  isRoot: boolean;
20
19
  meta?: any;
21
20
  sequence: number;
@@ -77,7 +77,7 @@ export declare function getNormalizedOrderDetails({ orderId, orderNumber }: {
77
77
  countryCode: string;
78
78
  currencyCode: string;
79
79
  deliveryId?: string;
80
- fullfilled?: Date;
80
+ fulfilled?: Date;
81
81
  ordered?: Date;
82
82
  orderNumber?: string;
83
83
  originEnrollmentId?: string;
@@ -9,7 +9,7 @@ export declare function getNormalizedQuotationDetails(quotationId: string, conte
9
9
  mediaId: string;
10
10
  } | null)[] | null;
11
11
  _id: string;
12
- deleted?: Date;
12
+ deleted?: Date | null;
13
13
  avatarId?: string;
14
14
  emails: import("@unchainedshop/core-users").Email[];
15
15
  guest: boolean;
@@ -81,7 +81,7 @@ export declare function getNormalizedQuotationDetails(quotationId: string, conte
81
81
  countryCode?: string;
82
82
  currencyCode?: string;
83
83
  expires?: Date;
84
- fullfilled?: Date;
84
+ fulfilled?: Date;
85
85
  meta?: any;
86
86
  price?: number;
87
87
  productId: string;
@@ -20,7 +20,7 @@ export declare function getNormalizedUserDetails(userId: string, context: Contex
20
20
  web3Addresses: any;
21
21
  reviews: import("@unchainedshop/core-products").ProductReview[];
22
22
  _id: string;
23
- deleted?: Date;
23
+ deleted?: Date | null;
24
24
  avatarId?: string;
25
25
  emails: import("@unchainedshop/core-users").Email[];
26
26
  guest: boolean;
@@ -9,6 +9,10 @@ export interface CryptoOptions {
9
9
  iv_size?: number;
10
10
  at_size?: number;
11
11
  }
12
+ type SerializedSession = session.SessionData | string;
13
+ type SerializeFunction = (session: session.SessionData) => SerializedSession;
14
+ type UnserializeFunction = (data: any) => session.SessionData;
15
+ type TransformIdFunction = (sessionId: string) => string;
12
16
  export interface ConnectMongoOptions {
13
17
  mongoUrl?: string;
14
18
  clientPromise?: Promise<MongoClient>;
@@ -22,14 +26,14 @@ export interface ConnectMongoOptions {
22
26
  createAutoRemoveIdx?: boolean;
23
27
  autoRemove?: 'native' | 'interval' | 'disabled';
24
28
  autoRemoveInterval?: number;
25
- serialize?: (a: any) => any;
26
- unserialize?: (a: any) => any;
29
+ serialize?: SerializeFunction;
30
+ unserialize?: UnserializeFunction;
27
31
  writeOperationOptions?: WriteConcernSettings;
28
- transformId?: (a: any) => any;
32
+ transformId?: TransformIdFunction;
29
33
  }
30
34
  interface InternalSessionType {
31
35
  _id: string;
32
- session: any;
36
+ session: SerializedSession;
33
37
  expires?: Date;
34
38
  lastModified?: Date;
35
39
  }
@@ -53,7 +57,7 @@ export default class MongoStore extends session.Store {
53
57
  }, callback?: (err: any) => void): void;
54
58
  all(callback: (err: any, obj?: session.SessionData[] | Record<string, session.SessionData> | null) => void): void;
55
59
  destroy(sid: string, callback?: (err: any) => void): void;
56
- length(callback: (err: any, length: number) => void): void;
60
+ length(callback: (err: any, length?: number) => void): void;
57
61
  clear(callback?: (err: any) => void): void;
58
62
  close(): Promise<void>;
59
63
  }
@@ -6,15 +6,15 @@ import { createLogger } from '@unchainedshop/logger';
6
6
  const logger = createLogger('unchained:api');
7
7
  const noop = () => { };
8
8
  const unit = (a) => a;
9
- function defaultSerializeFunction(session) {
9
+ function defaultSerializeFunction(sessionData) {
10
10
  const obj = {};
11
- let prop;
12
- for (prop in session) {
11
+ for (const prop in sessionData) {
13
12
  if (prop === 'cookie') {
14
- obj.cookie = session.cookie.toJSON ? session.cookie.toJSON() : session.cookie;
13
+ const cookie = sessionData.cookie;
14
+ obj.cookie = cookie.toJSON ? cookie.toJSON() : sessionData.cookie;
15
15
  }
16
16
  else {
17
- obj[prop] = session[prop];
17
+ obj[prop] = sessionData[prop];
18
18
  }
19
19
  }
20
20
  return obj;
@@ -135,12 +135,15 @@ export default class MongoStore extends session.Store {
135
135
  }
136
136
  return util.promisify(this.crypto.get).bind(this.crypto);
137
137
  }
138
- async decryptSession(session) {
139
- if (this.crypto && session) {
140
- const plaintext = await this.cryptoGet(this.options.crypto.secret, session.session).catch((err) => {
141
- throw new Error(err);
138
+ async decryptSession(internalSession) {
139
+ if (this.crypto && internalSession) {
140
+ const encryptedData = typeof internalSession.session === 'string'
141
+ ? internalSession.session
142
+ : JSON.stringify(internalSession.session);
143
+ const plaintext = await this.cryptoGet(this.options.crypto.secret, encryptedData).catch((err) => {
144
+ throw new Error(err.message);
142
145
  });
143
- session.session = JSON.parse(plaintext);
146
+ internalSession.session = JSON.parse(plaintext);
144
147
  }
145
148
  }
146
149
  get(sid, callback) {
@@ -148,16 +151,17 @@ export default class MongoStore extends session.Store {
148
151
  try {
149
152
  logger.debug(`MongoStore#get=${sid}`);
150
153
  const collection = await this.collectionP;
151
- const session = await collection.findOne({
154
+ const internalSession = await collection.findOne({
152
155
  _id: this.computeStorageId(sid),
153
156
  $or: [{ expires: { $exists: false } }, { expires: { $gt: new Date() } }],
154
157
  });
155
- if (this.crypto && session) {
156
- await this.decryptSession(session).catch((err) => callback(err));
158
+ if (this.crypto && internalSession) {
159
+ await this.decryptSession(internalSession).catch((err) => callback(err));
157
160
  }
158
- const s = session && this.transformFunctions.unserialize(session.session);
159
- if (this.options.touchAfter > 0 && session?.lastModified) {
160
- s.lastModified = session.lastModified;
161
+ const s = internalSession && this.transformFunctions.unserialize(internalSession.session);
162
+ if (this.options.touchAfter > 0 && internalSession?.lastModified) {
163
+ s.lastModified =
164
+ internalSession.lastModified;
161
165
  }
162
166
  this.emit('get', sid);
163
167
  callback(null, s === undefined ? null : s);
@@ -171,8 +175,9 @@ export default class MongoStore extends session.Store {
171
175
  (async () => {
172
176
  try {
173
177
  logger.debug(`MongoStore#set=${sid}`);
174
- if (this.options.touchAfter > 0 && session?.lastModified) {
175
- delete session.lastModified;
178
+ const sessionWithMeta = session;
179
+ if (this.options.touchAfter > 0 && sessionWithMeta.lastModified) {
180
+ delete sessionWithMeta.lastModified;
176
181
  }
177
182
  const s = {
178
183
  _id: this.computeStorageId(sid),
@@ -189,8 +194,9 @@ export default class MongoStore extends session.Store {
189
194
  }
190
195
  if (this.crypto) {
191
196
  const cryptoSet = util.promisify(this.crypto.set).bind(this.crypto);
192
- const data = await cryptoSet(this.options.crypto.secret, s.session).catch((err) => {
193
- throw new Error(err);
197
+ const sessionString = typeof s.session === 'string' ? s.session : JSON.stringify(s.session);
198
+ const data = await cryptoSet(this.options.crypto.secret, sessionString).catch((err) => {
199
+ throw new Error(err.message);
194
200
  });
195
201
  s.session = data;
196
202
  }
@@ -255,15 +261,15 @@ export default class MongoStore extends session.Store {
255
261
  try {
256
262
  logger.debug('MongoStore#all()');
257
263
  const collection = await this.collectionP;
258
- const sessions = collection.find({
264
+ const internalSessions = collection.find({
259
265
  $or: [{ expires: { $exists: false } }, { expires: { $gt: new Date() } }],
260
266
  });
261
267
  const results = [];
262
- for await (const session of sessions) {
263
- if (this.crypto && session) {
264
- await this.decryptSession(session);
268
+ for await (const internalSession of internalSessions) {
269
+ if (this.crypto && internalSession) {
270
+ await this.decryptSession(internalSession);
265
271
  }
266
- results.push(this.transformFunctions.unserialize(session.session));
272
+ results.push(this.transformFunctions.unserialize(internalSession.session));
267
273
  }
268
274
  this.emit('all', results);
269
275
  callback(null, results);
@@ -1,4 +1,4 @@
1
1
  import type { Context } from '../../../context.ts';
2
2
  export default function addWeb3Address(root: never, { address }: {
3
- address: any;
4
- }, { modules, userId, user }: Context): Promise<import("@unchainedshop/core-users").User | null | undefined>;
3
+ address: string;
4
+ }, { modules, userId, user }: Context): Promise<import("@unchainedshop/core-users").User | null>;
@@ -7,18 +7,5 @@ export default async function addWeb3Address(root, { address }, { modules, userI
7
7
  if (!address) {
8
8
  throw new UserWeb3InvalidAddressError({ userId, address });
9
9
  }
10
- const foundAlreadyExistingEntryForAddress = user.services?.web3?.some((service) => {
11
- return service.address === address;
12
- });
13
- if (foundAlreadyExistingEntryForAddress)
14
- return user;
15
- const nonce = Math.floor(Math.random() * 1000000).toString();
16
- return modules.users.updateUser({ _id: userId }, {
17
- $push: {
18
- 'services.web3': {
19
- address,
20
- nonce,
21
- },
22
- },
23
- }, {});
10
+ return modules.users.addWeb3Address(userId, address);
24
11
  }
@@ -1,4 +1,4 @@
1
1
  import type { Context } from '../../../context.ts';
2
- export default function addWebAuthnCredentials(root: never, { credentials }: {
2
+ export default function addWebAuthnCredentials(_root: never, { credentials }: {
3
3
  credentials: any;
4
- }, { modules, userId, user }: Context): Promise<import("mongodb").WithId<import("@unchainedshop/core-users").User> | null>;
4
+ }, { modules, userId, user }: Context): Promise<import("@unchainedshop/core-users").User | null>;
@@ -1,15 +1,11 @@
1
1
  import { log } from '@unchainedshop/logger';
2
2
  import { WebAuthnDisabledError } from "../../../errors.js";
3
- export default async function addWebAuthnCredentials(root, { credentials }, { modules, userId, user }) {
3
+ export default async function addWebAuthnCredentials(_root, { credentials }, { modules, userId, user }) {
4
4
  log(`mutation addWebAuthnCredentials ${user.username}`, {
5
5
  userId,
6
6
  });
7
7
  const webAuthnService = await modules.users.webAuthn.verifyCredentialCreation(user.username, credentials);
8
8
  if (!webAuthnService)
9
9
  throw new WebAuthnDisabledError();
10
- return modules.users.updateUser({ _id: userId }, {
11
- $push: {
12
- 'services.webAuthn': webAuthnService,
13
- },
14
- }, {});
10
+ return modules.users.addWebAuthnCredential(userId, webAuthnService);
15
11
  }
@@ -1,5 +1,5 @@
1
1
  import { log } from '@unchainedshop/logger';
2
- import { AuthOperationFailedError, EmailAlreadyExistsError, UsernameAlreadyExistsError, UsernameOrEmailRequiredError, PasswordOrWebAuthnPublicKeyRequiredError, PasswordInvalidError, } from "../../../errors.js";
2
+ import { AuthOperationFailedError, EmailAlreadyExistsError, UsernameAlreadyExistsError, UsernameOrEmailRequiredError, PasswordOrWebAuthnPublicKeyRequiredError, PasswordInvalidError, WebAuthnVerificationFailedError, } from "../../../errors.js";
3
3
  export default async function createUser(root, params, context) {
4
4
  const { modules, userId } = context;
5
5
  log('mutation createUser', { email: params.email, username: params.username, userId });
@@ -36,6 +36,8 @@ export default async function createUser(root, params, context) {
36
36
  throw new UsernameAlreadyExistsError({ username: params?.username });
37
37
  else if (e.cause === 'PASSWORD_INVALID')
38
38
  throw new PasswordInvalidError({ username: params?.username });
39
+ else if (e.cause === 'WEBAUTHN_INVALID')
40
+ throw new WebAuthnVerificationFailedError({ username: params?.username });
39
41
  else
40
42
  throw new AuthOperationFailedError({ username: params?.username, email: params.email });
41
43
  }