@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.
- package/README.md +204 -0
- package/lib/api-index.js +3 -0
- package/lib/chat/generateImageHandler.d.ts +7 -1
- package/lib/chat/generateImageHandler.js +4 -5
- package/lib/context.js +2 -13
- package/lib/errors.d.ts +1 -0
- package/lib/errors.js +2 -1
- package/lib/events.js +0 -2
- package/lib/express/chatHandler.js +4 -4
- package/lib/express/createERCMetadataMiddleware.js +1 -1
- package/lib/express/index.js +23 -9
- package/lib/fastify/chatHandler.js +4 -4
- package/lib/fastify/ercMetadataHandler.js +1 -1
- package/lib/fastify/index.js +9 -3
- package/lib/loaders/assortmentMediaTextLoader.js +1 -1
- package/lib/loaders/assortmentMediasLoader.js +1 -1
- package/lib/loaders/assortmentTextLoader.js +1 -1
- package/lib/loaders/countryLoader.js +1 -1
- package/lib/loaders/currencyLoader.js +1 -1
- package/lib/loaders/deliveryProviderLoader.js +1 -1
- package/lib/loaders/fileLoader.js +1 -1
- package/lib/loaders/filterTextLoader.js +1 -1
- package/lib/loaders/languageLoader.js +1 -1
- package/lib/loaders/orderLoader.js +1 -1
- package/lib/loaders/paymentProviderLoader.js +1 -1
- package/lib/loaders/productBySKULoader.js +2 -4
- package/lib/loaders/productLoader.js +1 -3
- package/lib/loaders/productMediaTextLoader.js +1 -1
- package/lib/loaders/productMediasLoader.js +1 -1
- package/lib/loaders/productProxiesLoader.js +2 -10
- package/lib/loaders/productTextLoader.js +1 -1
- package/lib/loaders/productVariationByKeyLoader.js +1 -1
- package/lib/loaders/productVariationLoader.js +1 -1
- package/lib/loaders/productVariationTextLoader.js +1 -1
- package/lib/loaders/quotationLoader.js +1 -1
- package/lib/loaders/userLoader.js +1 -1
- package/lib/loaders/warehousingProviderLoader.js +1 -1
- package/lib/mcp/tools/assortment/handlers/addAssortmentFilter.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/addAssortmentLink.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/addAssortmentMedia.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/addAssortmentProduct.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/createAssortment.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/getAssortment.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/getAssortmentChildren.d.ts +0 -2
- package/lib/mcp/tools/assortment/handlers/getAssortmentFilters.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/getAssortmentLinks.d.ts +0 -2
- package/lib/mcp/tools/assortment/handlers/getAssortmentMedia.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/getAssortmentProducts.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/index.d.ts +0 -2
- package/lib/mcp/tools/assortment/handlers/index.js +0 -2
- package/lib/mcp/tools/assortment/handlers/listAssortments.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/reorderAssortmentLinks.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/searchAssortmentProducts.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/updateAssortment.d.ts +0 -1
- package/lib/mcp/tools/assortment/handlers/updateAssortmentStatus.d.ts +0 -1
- package/lib/mcp/tools/assortment/schemas.d.ts +0 -5
- package/lib/mcp/tools/assortment/schemas.js +0 -4
- package/lib/mcp/tools/order/handlers/confirmOrder.d.ts +1 -1
- package/lib/mcp/tools/order/handlers/deliverOrder.d.ts +1 -1
- package/lib/mcp/tools/order/handlers/getOrder.d.ts +1 -1
- package/lib/mcp/tools/order/handlers/getTopCustomers.d.ts +6 -6
- package/lib/mcp/tools/order/handlers/getTopCustomers.js +5 -55
- package/lib/mcp/tools/order/handlers/getTopProducts.d.ts +3 -3
- package/lib/mcp/tools/order/handlers/getTopProducts.js +4 -43
- package/lib/mcp/tools/order/handlers/getUserCart.d.ts +1 -1
- package/lib/mcp/tools/order/handlers/listOrders.d.ts +1 -1
- package/lib/mcp/tools/order/handlers/payOrder.d.ts +1 -1
- package/lib/mcp/tools/order/handlers/rejectOrder.d.ts +1 -1
- package/lib/mcp/tools/provider/handlers/listProviders.js +4 -8
- package/lib/mcp/tools/quotation/handlers/getQuotation.d.ts +2 -2
- package/lib/mcp/tools/quotation/handlers/listQuotations.d.ts +2 -2
- package/lib/mcp/tools/quotation/handlers/makeQuotationProposal.d.ts +2 -2
- package/lib/mcp/tools/quotation/handlers/rejectQuotation.d.ts +2 -2
- package/lib/mcp/tools/quotation/handlers/rejectQuotation.js +1 -1
- package/lib/mcp/tools/quotation/handlers/verifyQuotation.d.ts +2 -2
- package/lib/mcp/tools/quotation/index.js +1 -1
- package/lib/mcp/tools/quotation/schemas.d.ts +5 -5
- package/lib/mcp/tools/quotation/schemas.js +3 -3
- package/lib/mcp/tools/system/schemas.d.ts +6 -6
- package/lib/mcp/tools/system/schemas.js +14 -7
- package/lib/mcp/tools/users/handlers/addUserEmail.d.ts +1 -1
- package/lib/mcp/tools/users/handlers/createUser.d.ts +1 -1
- package/lib/mcp/tools/users/handlers/enrollUser.d.ts +1 -1
- package/lib/mcp/tools/users/handlers/getCurrentUser.d.ts +1 -1
- package/lib/mcp/tools/users/handlers/getUser.d.ts +1 -1
- package/lib/mcp/tools/users/handlers/getUserOrders.d.ts +1 -1
- package/lib/mcp/tools/users/handlers/getUserQuotations.d.ts +1 -1
- package/lib/mcp/tools/users/handlers/listUsers.d.ts +1 -1
- package/lib/mcp/tools/users/handlers/setUserTags.d.ts +1 -1
- package/lib/mcp/tools/users/handlers/setUserUsername.d.ts +1 -1
- package/lib/mcp/tools/users/handlers/updateUser.d.ts +1 -1
- package/lib/mcp/utils/getNormalizedAssortmentDetails.d.ts +0 -1
- package/lib/mcp/utils/getNormalizedOrderDetails.d.ts +1 -1
- package/lib/mcp/utils/getNormalizedQuotationDetails.d.ts +2 -2
- package/lib/mcp/utils/getNormalizedUserDetails.d.ts +1 -1
- package/lib/mongo-store.d.ts +9 -5
- package/lib/mongo-store.js +31 -25
- package/lib/resolvers/mutations/accounts/addWeb3Address.d.ts +2 -2
- package/lib/resolvers/mutations/accounts/addWeb3Address.js +1 -14
- package/lib/resolvers/mutations/accounts/addWebAuthnCredentials.d.ts +2 -2
- package/lib/resolvers/mutations/accounts/addWebAuthnCredentials.js +2 -6
- package/lib/resolvers/mutations/accounts/createUser.js +3 -1
- package/lib/resolvers/mutations/accounts/createWebAuthnCredentialCreationOptions.d.ts +1 -4
- package/lib/resolvers/mutations/accounts/createWebAuthnCredentialRequestOptions.d.ts +1 -4
- package/lib/resolvers/mutations/accounts/forgotPassword.js +4 -4
- package/lib/resolvers/mutations/accounts/loginAsGuest.js +1 -3
- package/lib/resolvers/mutations/accounts/removeWeb3Address.d.ts +1 -1
- package/lib/resolvers/mutations/accounts/removeWeb3Address.js +3 -7
- package/lib/resolvers/mutations/accounts/removeWebAuthnCredentials.d.ts +1 -1
- package/lib/resolvers/mutations/accounts/removeWebAuthnCredentials.js +1 -5
- package/lib/resolvers/mutations/accounts/verifyWeb3Address.d.ts +2 -2
- package/lib/resolvers/mutations/accounts/verifyWeb3Address.js +8 -89
- package/lib/resolvers/mutations/filters/removeFilter.d.ts +2 -2
- package/lib/resolvers/mutations/filters/removeFilter.js +3 -5
- package/lib/resolvers/mutations/index.d.ts +0 -1
- package/lib/resolvers/mutations/index.js +0 -2
- package/lib/resolvers/mutations/orders/addMultipleCartProducts.js +23 -31
- package/lib/resolvers/mutations/orders/removeCartDiscount.d.ts +2 -2
- package/lib/resolvers/mutations/orders/removeCartDiscount.js +9 -14
- package/lib/resolvers/mutations/orders/updateCart.js +2 -8
- package/lib/resolvers/mutations/quotations/rejectQuotation.js +1 -1
- package/lib/resolvers/mutations/users/removeUser.d.ts +1 -1
- package/lib/resolvers/mutations/users/removeUser.js +2 -3
- package/lib/resolvers/mutations/warehousing/exportToken.js +9 -17
- package/lib/resolvers/queries/payment/paymentProvidersCount.d.ts +3 -3
- package/lib/resolvers/queries/payment/paymentProvidersCount.js +1 -1
- package/lib/resolvers/queries/shopInfo.js +4 -36
- package/lib/resolvers/type/delivery-provider-interface.d.ts +1 -7
- package/lib/resolvers/type/delivery-provider-interface.js +10 -20
- package/lib/resolvers/type/delivery-provider-pickup-types.d.ts +1 -7
- package/lib/resolvers/type/delivery-provider-shipping-types.d.ts +1 -7
- package/lib/resolvers/type/delivery-provider-types.d.ts +1 -7
- package/lib/resolvers/type/index.d.ts +33 -54
- package/lib/resolvers/type/media-types.d.ts +1 -1
- package/lib/resolvers/type/media-types.js +7 -5
- package/lib/resolvers/type/order/order-item-types.d.ts +2 -9
- package/lib/resolvers/type/order/order-item-types.js +2 -37
- package/lib/resolvers/type/order/order-statistics-types.d.ts +10 -10
- package/lib/resolvers/type/order/order-statistics-types.js +10 -64
- package/lib/resolvers/type/payment/payment-provider-types.d.ts +1 -7
- package/lib/resolvers/type/payment/payment-provider-types.js +7 -17
- package/lib/resolvers/type/price-types.d.ts +0 -1
- package/lib/resolvers/type/product/product-bundle-types.d.ts +1 -1
- package/lib/resolvers/type/product/product-configurable-types.d.ts +1 -1
- package/lib/resolvers/type/product/product-configurable-types.js +9 -32
- package/lib/resolvers/type/product/product-plan-types.d.ts +1 -1
- package/lib/resolvers/type/product/product-simple-types.d.ts +1 -1
- package/lib/resolvers/type/product/product-tokenized-types.d.ts +1 -1
- package/lib/resolvers/type/product/product-types.d.ts +1 -1
- package/lib/resolvers/type/product/product-types.js +7 -17
- package/lib/resolvers/type/shop-types.js +2 -5
- package/lib/resolvers/type/token-types.d.ts +3 -3
- package/lib/resolvers/type/token-types.js +4 -25
- package/lib/resolvers/type/user-types.js +1 -4
- package/lib/resolvers/type/webauthn-credentials-types.d.ts +10 -1
- package/lib/roles/index.d.ts +2 -1
- package/lib/roles/index.js +7 -1
- package/lib/schema/mutation.js +1 -7
- package/lib/schema/types/assortment.js +0 -1
- package/lib/schema/types/order/order.js +2 -2
- package/lib/schema/types/quotation.js +2 -2
- package/lib/utils/getConfiguredTags.d.ts +1 -0
- package/lib/utils/getConfiguredTags.js +9 -0
- package/package.json +14 -23
- package/lib/mcp/tools/assortment/handlers/setAssortmentBase.d.ts +0 -28
- package/lib/mcp/tools/assortment/handlers/setAssortmentBase.js +0 -11
- package/lib/resolvers/mutations/assortments/setBaseAssortment.d.ts +0 -4
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
'
|
|
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
|
|
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
|
|
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.
|
|
65
|
-
finished: z.ZodOptional<z.
|
|
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.
|
|
155
|
-
finished: z.ZodOptional<z.
|
|
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.
|
|
204
|
-
finished: z.ZodOptional<z.
|
|
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
|
|
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
|
-
.
|
|
114
|
+
.string()
|
|
115
|
+
.datetime()
|
|
111
116
|
.optional()
|
|
112
|
-
.describe('
|
|
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
|
-
.
|
|
227
|
+
.string()
|
|
228
|
+
.datetime()
|
|
223
229
|
.optional()
|
|
224
|
-
.describe('
|
|
230
|
+
.describe('ISO 8601 start timestamp for WORKER_FINISH_WORK action. When worker began execution.'),
|
|
225
231
|
finished: z
|
|
226
|
-
.
|
|
232
|
+
.string()
|
|
233
|
+
.datetime()
|
|
227
234
|
.optional()
|
|
228
|
-
.describe('
|
|
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
|
-
|
|
79
|
+
fulfilled?: Date;
|
|
80
80
|
ordered?: Date;
|
|
81
81
|
orderNumber?: string;
|
|
82
82
|
originEnrollmentId?: 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
|
-
|
|
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
|
-
|
|
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;
|
package/lib/mongo-store.d.ts
CHANGED
|
@@ -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?:
|
|
26
|
-
unserialize?:
|
|
29
|
+
serialize?: SerializeFunction;
|
|
30
|
+
unserialize?: UnserializeFunction;
|
|
27
31
|
writeOperationOptions?: WriteConcernSettings;
|
|
28
|
-
transformId?:
|
|
32
|
+
transformId?: TransformIdFunction;
|
|
29
33
|
}
|
|
30
34
|
interface InternalSessionType {
|
|
31
35
|
_id: string;
|
|
32
|
-
session:
|
|
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
|
|
60
|
+
length(callback: (err: any, length?: number) => void): void;
|
|
57
61
|
clear(callback?: (err: any) => void): void;
|
|
58
62
|
close(): Promise<void>;
|
|
59
63
|
}
|
package/lib/mongo-store.js
CHANGED
|
@@ -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(
|
|
9
|
+
function defaultSerializeFunction(sessionData) {
|
|
10
10
|
const obj = {};
|
|
11
|
-
|
|
12
|
-
for (prop in session) {
|
|
11
|
+
for (const prop in sessionData) {
|
|
13
12
|
if (prop === 'cookie') {
|
|
14
|
-
|
|
13
|
+
const cookie = sessionData.cookie;
|
|
14
|
+
obj.cookie = cookie.toJSON ? cookie.toJSON() : sessionData.cookie;
|
|
15
15
|
}
|
|
16
16
|
else {
|
|
17
|
-
obj[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(
|
|
139
|
-
if (this.crypto &&
|
|
140
|
-
const
|
|
141
|
-
|
|
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
|
-
|
|
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
|
|
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 &&
|
|
156
|
-
await this.decryptSession(
|
|
158
|
+
if (this.crypto && internalSession) {
|
|
159
|
+
await this.decryptSession(internalSession).catch((err) => callback(err));
|
|
157
160
|
}
|
|
158
|
-
const s =
|
|
159
|
-
if (this.options.touchAfter > 0 &&
|
|
160
|
-
s.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
|
-
|
|
175
|
-
|
|
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
|
|
193
|
-
|
|
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
|
|
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
|
|
263
|
-
if (this.crypto &&
|
|
264
|
-
await this.decryptSession(
|
|
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(
|
|
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:
|
|
4
|
-
}, { modules, userId, user }: Context): Promise<import("@unchainedshop/core-users").User | null
|
|
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
|
-
|
|
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(
|
|
2
|
+
export default function addWebAuthnCredentials(_root: never, { credentials }: {
|
|
3
3
|
credentials: any;
|
|
4
|
-
}, { modules, userId, user }: Context): Promise<import("
|
|
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(
|
|
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.
|
|
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
|
}
|