@labdigital/commercetools-mock 2.65.1 → 3.0.0-beta.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 +31 -8
- package/dist/abstract-BKFcva6S.mjs +1044 -0
- package/dist/abstract-BKFcva6S.mjs.map +1 -0
- package/dist/config-BcNSzPZz.d.mts +1718 -0
- package/dist/index.d.mts +50 -1633
- package/dist/index.mjs +3771 -2654
- package/dist/index.mjs.map +1 -1
- package/dist/storage/sqlite.d.mts +59 -0
- package/dist/storage/sqlite.mjs +234 -0
- package/dist/storage/sqlite.mjs.map +1 -0
- package/package.json +26 -29
- package/src/ctMock.ts +125 -136
- package/src/helpers.ts +14 -6
- package/src/index.ts +5 -0
- package/src/lib/masking.ts +4 -5
- package/src/lib/product-review-statistics.test.ts +257 -294
- package/src/lib/review-statistics.ts +17 -4
- package/src/oauth/helpers.ts +7 -4
- package/src/oauth/server.test.ts +102 -62
- package/src/oauth/server.ts +215 -213
- package/src/oauth/store.ts +20 -6
- package/src/orderSearch.ts +3 -3
- package/src/product-projection-search.ts +38 -20
- package/src/product-search-availability.test.ts +31 -52
- package/src/product-search.ts +19 -10
- package/src/projectAPI.ts +6 -22
- package/src/repositories/abstract.ts +182 -48
- package/src/repositories/as-associate.test.ts +19 -19
- package/src/repositories/associate-role.ts +12 -23
- package/src/repositories/attribute-group.test.ts +23 -23
- package/src/repositories/attribute-group.ts +6 -4
- package/src/repositories/business-unit.test.ts +63 -57
- package/src/repositories/business-unit.ts +107 -55
- package/src/repositories/cart/actions.ts +96 -65
- package/src/repositories/cart/helpers.ts +15 -11
- package/src/repositories/cart/index.test.ts +136 -30
- package/src/repositories/cart/index.ts +76 -59
- package/src/repositories/cart-discount/actions.ts +12 -44
- package/src/repositories/cart-discount/index.ts +20 -8
- package/src/repositories/category/actions.ts +27 -27
- package/src/repositories/category/index.test.ts +13 -9
- package/src/repositories/category/index.ts +40 -23
- package/src/repositories/channel.test.ts +53 -51
- package/src/repositories/channel.ts +12 -22
- package/src/repositories/custom-object.ts +34 -25
- package/src/repositories/customer/actions.ts +47 -25
- package/src/repositories/customer/index.test.ts +11 -11
- package/src/repositories/customer/index.ts +65 -35
- package/src/repositories/customer-group.test.ts +44 -42
- package/src/repositories/customer-group.ts +12 -22
- package/src/repositories/discount-code/actions.ts +3 -19
- package/src/repositories/discount-code/index.ts +9 -4
- package/src/repositories/discount-group/index.ts +8 -3
- package/src/repositories/extension.test.ts +27 -27
- package/src/repositories/extension.ts +10 -5
- package/src/repositories/helpers.ts +126 -47
- package/src/repositories/inventory-entry/actions.ts +3 -24
- package/src/repositories/inventory-entry/index.ts +19 -11
- package/src/repositories/my-customer.ts +13 -12
- package/src/repositories/my-order.ts +5 -2
- package/src/repositories/order/actions.ts +89 -56
- package/src/repositories/order/index.test.ts +36 -31
- package/src/repositories/order/index.ts +83 -49
- package/src/repositories/order-edit.ts +8 -3
- package/src/repositories/payment/actions.ts +64 -44
- package/src/repositories/payment/helpers.ts +3 -3
- package/src/repositories/payment/index.ts +28 -12
- package/src/repositories/product/actions.ts +133 -98
- package/src/repositories/product/helpers.ts +29 -16
- package/src/repositories/product/index.ts +42 -25
- package/src/repositories/product-discount.ts +6 -4
- package/src/repositories/product-projection.ts +41 -21
- package/src/repositories/product-selection.ts +8 -15
- package/src/repositories/product-tailoring.ts +22 -3
- package/src/repositories/product-type.ts +45 -4
- package/src/repositories/project.ts +57 -13
- package/src/repositories/quote/actions.ts +5 -28
- package/src/repositories/quote/index.ts +29 -6
- package/src/repositories/quote-request/actions.ts +5 -28
- package/src/repositories/quote-request/index.test.ts +3 -3
- package/src/repositories/quote-request/index.ts +31 -11
- package/src/repositories/quote-staged/actions.ts +5 -28
- package/src/repositories/quote-staged/index.ts +22 -8
- package/src/repositories/recurrence-policy/index.ts +6 -4
- package/src/repositories/recurring-order/actions.ts +7 -32
- package/src/repositories/recurring-order/index.ts +8 -6
- package/src/repositories/review.test.ts +147 -142
- package/src/repositories/review.ts +31 -37
- package/src/repositories/shipping-method/actions.ts +11 -28
- package/src/repositories/shipping-method/index.ts +26 -15
- package/src/repositories/shopping-list/actions.ts +21 -31
- package/src/repositories/shopping-list/index.ts +44 -22
- package/src/repositories/standalone-price.ts +6 -4
- package/src/repositories/state.ts +15 -9
- package/src/repositories/store.ts +21 -32
- package/src/repositories/subscription.test.ts +22 -22
- package/src/repositories/subscription.ts +8 -3
- package/src/repositories/tax-category/index.ts +8 -3
- package/src/repositories/type/actions.ts +21 -3
- package/src/repositories/type/index.ts +5 -3
- package/src/repositories/zone.test.ts +112 -77
- package/src/repositories/zone.ts +5 -3
- package/src/schemas/generated/associate-role.ts +13 -0
- package/src/schemas/generated/attribute-group.ts +12 -0
- package/src/schemas/generated/business-unit.ts +38 -0
- package/src/schemas/generated/cart-discount.ts +33 -0
- package/src/schemas/generated/cart.ts +61 -0
- package/src/schemas/generated/category.ts +25 -0
- package/src/schemas/generated/channel.ts +21 -0
- package/src/schemas/generated/common.ts +1372 -0
- package/src/schemas/generated/custom-object.ts +11 -0
- package/src/schemas/generated/customer-group.ts +11 -0
- package/src/schemas/generated/customer.ts +47 -0
- package/src/schemas/generated/discount-code.ts +25 -0
- package/src/schemas/generated/discount-group.ts +13 -0
- package/src/schemas/generated/extension.ts +15 -0
- package/src/schemas/generated/index.ts +42 -0
- package/src/schemas/generated/inventory-entry.ts +20 -0
- package/src/schemas/generated/my-quote-request.ts +10 -0
- package/src/schemas/generated/order-edit.ts +18 -0
- package/src/schemas/generated/order-from-cart.ts +25 -0
- package/src/schemas/generated/payment.ts +30 -0
- package/src/schemas/generated/product-discount.ts +20 -0
- package/src/schemas/generated/product-selection.ts +18 -0
- package/src/schemas/generated/product-tailoring.ts +26 -0
- package/src/schemas/generated/product-type.ts +12 -0
- package/src/schemas/generated/product.ts +37 -0
- package/src/schemas/generated/quote-request.ts +19 -0
- package/src/schemas/generated/quote.ts +18 -0
- package/src/schemas/generated/recurrence-policy.ts +15 -0
- package/src/schemas/generated/recurring-order.ts +19 -0
- package/src/schemas/generated/review.ts +24 -0
- package/src/schemas/generated/shipping-method.ts +24 -0
- package/src/schemas/generated/shopping-list.ts +28 -0
- package/src/schemas/generated/staged-quote.ts +18 -0
- package/src/schemas/generated/standalone-price.ts +32 -0
- package/src/schemas/generated/state.ts +20 -0
- package/src/schemas/generated/store.ts +23 -0
- package/src/schemas/generated/subscription.ts +20 -0
- package/src/schemas/generated/tax-category.ts +12 -0
- package/src/schemas/generated/type.ts +17 -0
- package/src/schemas/generated/zone.ts +12 -0
- package/src/schemas/update-request.ts +3 -5
- package/src/server.ts +32 -4
- package/src/services/abstract.ts +207 -101
- package/src/services/as-associate-cart.test.ts +28 -36
- package/src/services/as-associate-cart.ts +15 -12
- package/src/services/as-associate-order.test.ts +33 -40
- package/src/services/as-associate-order.ts +15 -12
- package/src/services/as-associate-quote-request.ts +15 -12
- package/src/services/as-associate-shopping-list.test.ts +25 -35
- package/src/services/as-associate-shopping-list.ts +15 -12
- package/src/services/as-associate.test.ts +21 -15
- package/src/services/as-associate.ts +23 -22
- package/src/services/associate-roles.test.ts +16 -22
- package/src/services/associate-roles.ts +2 -2
- package/src/services/attribute-group.test.ts +40 -44
- package/src/services/attribute-group.ts +2 -2
- package/src/services/business-units.test.ts +227 -163
- package/src/services/business-units.ts +2 -2
- package/src/services/cart-discount.test.ts +253 -187
- package/src/services/cart-discount.ts +2 -2
- package/src/services/cart.test.ts +833 -832
- package/src/services/cart.ts +31 -12
- package/src/services/category.test.ts +208 -130
- package/src/services/category.ts +2 -2
- package/src/services/channel.test.ts +39 -44
- package/src/services/channel.ts +2 -2
- package/src/services/custom-object.test.ts +103 -79
- package/src/services/custom-object.ts +106 -38
- package/src/services/customer-group.test.ts +39 -44
- package/src/services/customer-group.ts +2 -2
- package/src/services/customer.test.ts +357 -292
- package/src/services/customer.ts +70 -23
- package/src/services/discount-code.test.ts +57 -68
- package/src/services/discount-code.ts +2 -2
- package/src/services/discount-group.test.ts +111 -134
- package/src/services/discount-group.ts +2 -2
- package/src/services/draft-validation.test.ts +255 -0
- package/src/services/extension.test.ts +39 -44
- package/src/services/extension.ts +2 -2
- package/src/services/inventory-entry.test.ts +106 -87
- package/src/services/inventory-entry.ts +2 -2
- package/src/services/my-business-unit.test.ts +82 -112
- package/src/services/my-business-unit.ts +25 -19
- package/src/services/my-cart.test.ts +46 -41
- package/src/services/my-cart.ts +32 -28
- package/src/services/my-customer.test.ts +153 -88
- package/src/services/my-customer.ts +130 -61
- package/src/services/my-order.ts +15 -12
- package/src/services/my-payment.test.ts +30 -24
- package/src/services/my-payment.ts +2 -2
- package/src/services/my-shopping-list.ts +2 -2
- package/src/services/order.test.ts +332 -276
- package/src/services/order.ts +45 -27
- package/src/services/payment.test.ts +31 -29
- package/src/services/payment.ts +2 -2
- package/src/services/product-discount.test.ts +39 -46
- package/src/services/product-discount.ts +2 -2
- package/src/services/product-projection.test.ts +176 -166
- package/src/services/product-projection.ts +31 -15
- package/src/services/product-selection.test.ts +17 -9
- package/src/services/product-selection.ts +2 -2
- package/src/services/product-type.test.ts +80 -21
- package/src/services/product-type.ts +2 -2
- package/src/services/product.test.ts +569 -534
- package/src/services/product.ts +14 -7
- package/src/services/project.test.ts +22 -12
- package/src/services/project.ts +28 -13
- package/src/services/quote-request.test.ts +36 -39
- package/src/services/quote-request.ts +2 -2
- package/src/services/quote-staged.ts +2 -2
- package/src/services/quote.ts +2 -2
- package/src/services/recurrence-policy.test.ts +114 -139
- package/src/services/recurrence-policy.ts +2 -2
- package/src/services/recurring-order.test.ts +149 -194
- package/src/services/recurring-order.ts +2 -2
- package/src/services/reviews.test.ts +127 -106
- package/src/services/reviews.ts +2 -2
- package/src/services/shipping-method.test.ts +96 -125
- package/src/services/shipping-method.ts +24 -12
- package/src/services/shopping-list.test.ts +183 -141
- package/src/services/shopping-list.ts +2 -2
- package/src/services/standalone-price.test.ts +60 -46
- package/src/services/standalone-price.ts +2 -2
- package/src/services/state.test.ts +20 -25
- package/src/services/state.ts +2 -2
- package/src/services/store.test.ts +26 -45
- package/src/services/store.ts +2 -2
- package/src/services/subscription.test.ts +39 -44
- package/src/services/subscription.ts +2 -2
- package/src/services/tax-category.test.ts +33 -36
- package/src/services/tax-category.ts +2 -2
- package/src/services/type.test.ts +45 -44
- package/src/services/type.ts +2 -2
- package/src/services/zone.test.ts +40 -44
- package/src/services/zone.ts +2 -2
- package/src/shipping.ts +41 -11
- package/src/storage/abstract.ts +248 -17
- package/src/storage/in-memory.ts +147 -290
- package/src/storage/sqlite.ts +429 -0
- package/src/storage/storage-map.ts +75 -0
- package/src/storage/storage.test-helpers.ts +97 -0
- package/src/storage/storage.test.ts +802 -0
- package/src/testing/associate-role.ts +28 -0
- package/src/testing/attribute-group.ts +27 -0
- package/src/testing/business-unit.ts +9 -8
- package/src/testing/cart-discount.ts +34 -0
- package/src/testing/cart.ts +20 -0
- package/src/testing/category.ts +25 -0
- package/src/testing/channel.ts +23 -0
- package/src/testing/custom-object.ts +27 -0
- package/src/testing/customer-group.ts +26 -0
- package/src/testing/customer.ts +36 -33
- package/src/testing/discount-code.ts +29 -0
- package/src/testing/discount-group.ts +27 -0
- package/src/testing/extension.ts +32 -0
- package/src/testing/index.ts +33 -0
- package/src/testing/inventory-entry.ts +26 -0
- package/src/testing/order.ts +27 -0
- package/src/testing/payment.ts +23 -0
- package/src/testing/product-discount.ts +33 -0
- package/src/testing/product-selection.ts +28 -0
- package/src/testing/product-type.ts +27 -0
- package/src/testing/product.ts +38 -0
- package/src/testing/quote-request.ts +29 -0
- package/src/testing/recurrence-policy.ts +33 -0
- package/src/testing/recurring-order.ts +32 -0
- package/src/testing/review.ts +24 -0
- package/src/testing/shipping-method.ts +31 -0
- package/src/testing/shopping-list.ts +25 -0
- package/src/testing/standalone-price.ts +31 -0
- package/src/testing/state.ts +21 -0
- package/src/testing/store.ts +26 -0
- package/src/testing/subscription.ts +38 -0
- package/src/testing/tax-category.ts +27 -0
- package/src/testing/type.ts +9 -6
- package/src/testing/zone.ts +22 -0
- package/src/validate.test.ts +122 -0
- package/src/validate.ts +78 -7
- package/src/.env +0 -0
|
@@ -10,12 +10,12 @@ describe("Customer repository", () => {
|
|
|
10
10
|
const repository = new CustomerRepository(config);
|
|
11
11
|
|
|
12
12
|
test("query by lowercaseEmail", async () => {
|
|
13
|
-
const customer = repository.create(
|
|
13
|
+
const customer = await repository.create(
|
|
14
14
|
{ projectKey: "dummy" },
|
|
15
15
|
{ email: "my-customer-UPPERCASE@email.com" },
|
|
16
16
|
);
|
|
17
17
|
|
|
18
|
-
const result = repository.query(
|
|
18
|
+
const result = await repository.query(
|
|
19
19
|
{ projectKey: "dummy" },
|
|
20
20
|
{ where: [`lowercaseEmail = "my-customer-uppercase@email.com"`] },
|
|
21
21
|
);
|
|
@@ -25,18 +25,18 @@ describe("Customer repository", () => {
|
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
test("updating lowercaseEmail", async () => {
|
|
28
|
-
const customer = repository.create(
|
|
28
|
+
const customer = await repository.create(
|
|
29
29
|
{ projectKey: "dummy" },
|
|
30
30
|
{ email: "my-customer-UPPERCASE-v1@email.com" },
|
|
31
31
|
);
|
|
32
32
|
|
|
33
|
-
repository.saveUpdate({ projectKey: "dummy" }, customer.version, {
|
|
33
|
+
await repository.saveUpdate({ projectKey: "dummy" }, customer.version, {
|
|
34
34
|
...customer,
|
|
35
35
|
email: "my-customer-UPPERCASE-v2@email.com",
|
|
36
36
|
version: customer.version + 1,
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
const result = repository.query(
|
|
39
|
+
const result = await repository.query(
|
|
40
40
|
{ projectKey: "dummy" },
|
|
41
41
|
{ where: [`lowercaseEmail = "my-customer-uppercase-v2@email.com"`] },
|
|
42
42
|
);
|
|
@@ -81,10 +81,10 @@ describe("Customer repository", () => {
|
|
|
81
81
|
productSelections: [],
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
-
storage.add("dummy", "store", store1);
|
|
85
|
-
storage.add("dummy", "store", store2);
|
|
84
|
+
await storage.add("dummy", "store", store1);
|
|
85
|
+
await storage.add("dummy", "store", store2);
|
|
86
86
|
|
|
87
|
-
const result = repository.create(
|
|
87
|
+
const result = await repository.create(
|
|
88
88
|
{ projectKey: "dummy" },
|
|
89
89
|
{
|
|
90
90
|
email: "my-customer@email.com",
|
|
@@ -131,9 +131,9 @@ describe("Customer repository", () => {
|
|
|
131
131
|
productSelections: [],
|
|
132
132
|
};
|
|
133
133
|
|
|
134
|
-
storage.add("dummy", "store", store1);
|
|
134
|
+
await storage.add("dummy", "store", store1);
|
|
135
135
|
|
|
136
|
-
const result = repository.create(
|
|
136
|
+
const result = await repository.create(
|
|
137
137
|
{ projectKey: "dummy" },
|
|
138
138
|
{
|
|
139
139
|
email: "my-customer2@email.com",
|
|
@@ -155,7 +155,7 @@ describe("Customer repository", () => {
|
|
|
155
155
|
});
|
|
156
156
|
|
|
157
157
|
test("adding customer without linked stores", async () => {
|
|
158
|
-
const result = repository.create(
|
|
158
|
+
const result = await repository.create(
|
|
159
159
|
{ projectKey: "dummy" },
|
|
160
160
|
{
|
|
161
161
|
email: "my-customer-without-stores@email.com",
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
DuplicateFieldError,
|
|
9
9
|
InvalidInputError,
|
|
10
10
|
MyCustomerResetPassword,
|
|
11
|
+
RequiredFieldError,
|
|
11
12
|
ResourceNotFoundError,
|
|
12
13
|
Store,
|
|
13
14
|
StoreKeyReference,
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
validateEmailVerifyToken,
|
|
27
28
|
validatePasswordResetToken,
|
|
28
29
|
} from "#src/lib/password.ts";
|
|
30
|
+
import { CustomerDraftSchema } from "#src/schemas/generated/customer.ts";
|
|
29
31
|
import type { ResourceMap, ShallowWritable, Writable } from "#src/types.ts";
|
|
30
32
|
import {
|
|
31
33
|
AbstractResourceRepository,
|
|
@@ -38,13 +40,21 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
38
40
|
constructor(config: Config) {
|
|
39
41
|
super("customer", config);
|
|
40
42
|
this.actions = new CustomerUpdateHandler(config.storage);
|
|
43
|
+
this.draftSchema = CustomerDraftSchema;
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
create(
|
|
46
|
+
async create(
|
|
47
|
+
context: RepositoryContext,
|
|
48
|
+
draft: CustomerDraft,
|
|
49
|
+
): Promise<Customer> {
|
|
44
50
|
// Check uniqueness
|
|
45
|
-
const results = this._storage.query(
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
const results = await this._storage.query(
|
|
52
|
+
context.projectKey,
|
|
53
|
+
this.getTypeId(),
|
|
54
|
+
{
|
|
55
|
+
where: [`lowercaseEmail="${draft.email.toLowerCase()}"`],
|
|
56
|
+
},
|
|
57
|
+
);
|
|
48
58
|
if (results.count > 0) {
|
|
49
59
|
throw new CommercetoolsError<any>({
|
|
50
60
|
code: "CustomerAlreadyExists",
|
|
@@ -75,7 +85,14 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
75
85
|
if (addressId < addresses.length) {
|
|
76
86
|
const id = addresses[addressId].id;
|
|
77
87
|
if (!id) {
|
|
78
|
-
throw new
|
|
88
|
+
throw new CommercetoolsError<RequiredFieldError>(
|
|
89
|
+
{
|
|
90
|
+
code: "RequiredField",
|
|
91
|
+
message: "Address ID is missing",
|
|
92
|
+
field: "addressId",
|
|
93
|
+
},
|
|
94
|
+
400,
|
|
95
|
+
);
|
|
79
96
|
}
|
|
80
97
|
return id;
|
|
81
98
|
}
|
|
@@ -112,14 +129,14 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
112
129
|
let storesForCustomer: StoreKeyReference[] = [];
|
|
113
130
|
|
|
114
131
|
if (draft.stores && draft.stores.length > 0) {
|
|
115
|
-
storesForCustomer = this.storeReferenceToStoreKeyReference(
|
|
132
|
+
storesForCustomer = await this.storeReferenceToStoreKeyReference(
|
|
116
133
|
draft.stores,
|
|
117
134
|
context.projectKey,
|
|
118
135
|
);
|
|
119
136
|
}
|
|
120
137
|
|
|
121
138
|
const resource: Customer = {
|
|
122
|
-
...getBaseResourceProperties(),
|
|
139
|
+
...getBaseResourceProperties(context.clientId),
|
|
123
140
|
key: draft.key,
|
|
124
141
|
authenticationMode: draft.authenticationMode || "Password",
|
|
125
142
|
firstName: draft.firstName,
|
|
@@ -139,38 +156,43 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
139
156
|
defaultShippingAddressId: defaultShippingAddressId,
|
|
140
157
|
shippingAddressIds: shippingAddressIds,
|
|
141
158
|
billingAddressIds: billingAddressIds,
|
|
142
|
-
custom: createCustomFields(
|
|
159
|
+
custom: await createCustomFields(
|
|
143
160
|
draft.custom,
|
|
144
161
|
context.projectKey,
|
|
145
162
|
this._storage,
|
|
146
163
|
),
|
|
147
164
|
stores: storesForCustomer,
|
|
165
|
+
customerGroupAssignments: [],
|
|
148
166
|
} satisfies unknown as Customer;
|
|
149
167
|
|
|
150
|
-
return this.saveNew(context, resource);
|
|
168
|
+
return await this.saveNew(context, resource);
|
|
151
169
|
}
|
|
152
170
|
|
|
153
|
-
saveUpdate(
|
|
171
|
+
async saveUpdate(
|
|
154
172
|
context: RepositoryContext,
|
|
155
173
|
version: number,
|
|
156
174
|
resource: ShallowWritable<ResourceMap["customer"]>,
|
|
157
|
-
): ShallowWritable<ResourceMap["customer"]
|
|
175
|
+
): Promise<ShallowWritable<ResourceMap["customer"]>> {
|
|
158
176
|
// Also update lowercaseEmail attribute
|
|
159
177
|
const updatedResource: Customer = {
|
|
160
178
|
...resource,
|
|
161
179
|
lowercaseEmail: resource.email.toLowerCase(),
|
|
162
180
|
} satisfies unknown as Customer;
|
|
163
181
|
|
|
164
|
-
return super.saveUpdate(context, version, updatedResource);
|
|
182
|
+
return await super.saveUpdate(context, version, updatedResource);
|
|
165
183
|
}
|
|
166
184
|
|
|
167
|
-
passwordResetToken(
|
|
185
|
+
async passwordResetToken(
|
|
168
186
|
context: RepositoryContext,
|
|
169
187
|
request: CustomerCreatePasswordResetToken,
|
|
170
|
-
): CustomerToken {
|
|
171
|
-
const results = this._storage.query(
|
|
172
|
-
|
|
173
|
-
|
|
188
|
+
): Promise<CustomerToken> {
|
|
189
|
+
const results = await this._storage.query(
|
|
190
|
+
context.projectKey,
|
|
191
|
+
this.getTypeId(),
|
|
192
|
+
{
|
|
193
|
+
where: [`email="${request.email.toLocaleLowerCase()}"`],
|
|
194
|
+
},
|
|
195
|
+
);
|
|
174
196
|
if (results.count === 0) {
|
|
175
197
|
throw new CommercetoolsError<ResourceNotFoundError>({
|
|
176
198
|
code: "ResourceNotFound",
|
|
@@ -182,7 +204,7 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
182
204
|
|
|
183
205
|
const expiresAt = new Date(Date.now() + ttlMinutes * 60 * 1000);
|
|
184
206
|
const customer = results.results[0] as Customer;
|
|
185
|
-
const rest = getBaseResourceProperties();
|
|
207
|
+
const rest = getBaseResourceProperties(context.clientId);
|
|
186
208
|
|
|
187
209
|
const token = createPasswordResetToken(customer, expiresAt);
|
|
188
210
|
|
|
@@ -197,7 +219,7 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
197
219
|
};
|
|
198
220
|
}
|
|
199
221
|
|
|
200
|
-
passwordReset(
|
|
222
|
+
async passwordReset(
|
|
201
223
|
context: RepositoryContext,
|
|
202
224
|
resetPassword: CustomerResetPassword | MyCustomerResetPassword,
|
|
203
225
|
) {
|
|
@@ -211,11 +233,11 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
211
233
|
});
|
|
212
234
|
}
|
|
213
235
|
|
|
214
|
-
const customer = this._storage.get(
|
|
236
|
+
const customer = (await this._storage.get(
|
|
215
237
|
context.projectKey,
|
|
216
238
|
"customer",
|
|
217
239
|
customerId,
|
|
218
|
-
) as Writable<Customer> | undefined;
|
|
240
|
+
)) as Writable<Customer> | undefined;
|
|
219
241
|
|
|
220
242
|
if (!customer) {
|
|
221
243
|
throw new CommercetoolsError<ResourceNotFoundError>({
|
|
@@ -228,14 +250,21 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
228
250
|
customer.version += 1;
|
|
229
251
|
|
|
230
252
|
// Update storage
|
|
231
|
-
this._storage.add(context.projectKey, "customer", customer);
|
|
253
|
+
await this._storage.add(context.projectKey, "customer", customer);
|
|
232
254
|
return customer;
|
|
233
255
|
}
|
|
234
256
|
|
|
235
|
-
emailToken(
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
257
|
+
async emailToken(
|
|
258
|
+
context: RepositoryContext,
|
|
259
|
+
id: string,
|
|
260
|
+
): Promise<CustomerToken> {
|
|
261
|
+
const results = await this._storage.query(
|
|
262
|
+
context.projectKey,
|
|
263
|
+
this.getTypeId(),
|
|
264
|
+
{
|
|
265
|
+
where: [`id="${id.toLocaleLowerCase()}"`],
|
|
266
|
+
},
|
|
267
|
+
);
|
|
239
268
|
if (results.count === 0) {
|
|
240
269
|
throw new CommercetoolsError<ResourceNotFoundError>({
|
|
241
270
|
code: "ResourceNotFound",
|
|
@@ -244,7 +273,7 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
244
273
|
}
|
|
245
274
|
const expiresAt = new Date(Date.now() + 30 * 60);
|
|
246
275
|
const customer = results.results[0] as Customer;
|
|
247
|
-
const rest = getBaseResourceProperties();
|
|
276
|
+
const rest = getBaseResourceProperties(context.clientId);
|
|
248
277
|
|
|
249
278
|
const token = createEmailVerifyToken(customer);
|
|
250
279
|
return {
|
|
@@ -258,7 +287,7 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
258
287
|
};
|
|
259
288
|
}
|
|
260
289
|
|
|
261
|
-
emailTokenConfirm(
|
|
290
|
+
async emailTokenConfirm(
|
|
262
291
|
context: RepositoryContext,
|
|
263
292
|
request: { tokenValue: string },
|
|
264
293
|
) {
|
|
@@ -270,11 +299,11 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
270
299
|
});
|
|
271
300
|
}
|
|
272
301
|
|
|
273
|
-
const customer = this._storage.get(
|
|
302
|
+
const customer = (await this._storage.get(
|
|
274
303
|
context.projectKey,
|
|
275
304
|
"customer",
|
|
276
305
|
customerId,
|
|
277
|
-
) as Writable<Customer> | undefined;
|
|
306
|
+
)) as Writable<Customer> | undefined;
|
|
278
307
|
|
|
279
308
|
if (!customer) {
|
|
280
309
|
throw new CommercetoolsError<ResourceNotFoundError>({
|
|
@@ -287,14 +316,14 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
287
316
|
customer.version += 1;
|
|
288
317
|
|
|
289
318
|
// Update storage
|
|
290
|
-
this._storage.add(context.projectKey, "customer", customer);
|
|
319
|
+
await this._storage.add(context.projectKey, "customer", customer);
|
|
291
320
|
return customer;
|
|
292
321
|
}
|
|
293
322
|
|
|
294
|
-
private storeReferenceToStoreKeyReference(
|
|
323
|
+
private async storeReferenceToStoreKeyReference(
|
|
295
324
|
draftStores: StoreResourceIdentifier[],
|
|
296
325
|
projectKey: string,
|
|
297
|
-
): StoreKeyReference[] {
|
|
326
|
+
): Promise<StoreKeyReference[]> {
|
|
298
327
|
const storeIds = draftStores
|
|
299
328
|
.map((storeReference) => storeReference.id)
|
|
300
329
|
.filter(Boolean);
|
|
@@ -302,9 +331,10 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
|
|
|
302
331
|
let stores: Store[] = [];
|
|
303
332
|
|
|
304
333
|
if (storeIds.length > 0) {
|
|
305
|
-
|
|
334
|
+
const storeResult = await this._storage.query(projectKey, "store", {
|
|
306
335
|
where: storeIds.map((id) => `id="${id}"`),
|
|
307
|
-
})
|
|
336
|
+
});
|
|
337
|
+
stores = storeResult.results;
|
|
308
338
|
|
|
309
339
|
if (storeIds.length !== stores.length) {
|
|
310
340
|
throw new CommercetoolsError<ResourceNotFoundError>({
|
|
@@ -5,7 +5,7 @@ import type {
|
|
|
5
5
|
CustomerGroupSetCustomTypeAction,
|
|
6
6
|
CustomerGroupSetKeyAction,
|
|
7
7
|
} from "@commercetools/platform-sdk";
|
|
8
|
-
import { describe, expect, test } from "vitest";
|
|
8
|
+
import { beforeAll, describe, expect, test } from "vitest";
|
|
9
9
|
import type { Config } from "#src/config.ts";
|
|
10
10
|
import { getBaseResourceProperties } from "#src/helpers.ts";
|
|
11
11
|
import { InMemoryStorage } from "#src/storage/index.ts";
|
|
@@ -16,32 +16,34 @@ describe("CustomerGroup Repository", () => {
|
|
|
16
16
|
const config: Config = { storage, strict: false };
|
|
17
17
|
const repository = new CustomerGroupRepository(config);
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
19
|
+
beforeAll(async () => {
|
|
20
|
+
// Add a custom type for testing
|
|
21
|
+
await storage.add("dummy", "type", {
|
|
22
|
+
...getBaseResourceProperties(),
|
|
23
|
+
id: "custom-type-id",
|
|
24
|
+
key: "custom-type-key",
|
|
25
|
+
name: { "en-US": "Custom Type" },
|
|
26
|
+
resourceTypeIds: ["customer-group"],
|
|
27
|
+
fieldDefinitions: [
|
|
28
|
+
{
|
|
29
|
+
name: "description",
|
|
30
|
+
label: { "en-US": "Description" },
|
|
31
|
+
required: false,
|
|
32
|
+
type: { name: "String" },
|
|
33
|
+
inputHint: "SingleLine",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
});
|
|
35
37
|
});
|
|
36
38
|
|
|
37
|
-
test("create customer group", () => {
|
|
39
|
+
test("create customer group", async () => {
|
|
38
40
|
const draft: CustomerGroupDraft = {
|
|
39
41
|
key: "premium-customers",
|
|
40
42
|
groupName: "Premium Customers",
|
|
41
43
|
};
|
|
42
44
|
|
|
43
45
|
const ctx = { projectKey: "dummy" };
|
|
44
|
-
const result = repository.create(ctx, draft);
|
|
46
|
+
const result = await repository.create(ctx, draft);
|
|
45
47
|
|
|
46
48
|
expect(result.id).toBeDefined();
|
|
47
49
|
expect(result.version).toBe(1);
|
|
@@ -50,12 +52,12 @@ describe("CustomerGroup Repository", () => {
|
|
|
50
52
|
expect(result.custom).toBeUndefined();
|
|
51
53
|
|
|
52
54
|
// Test that the customer group is stored
|
|
53
|
-
const items = repository.query(ctx);
|
|
55
|
+
const items = await repository.query(ctx);
|
|
54
56
|
expect(items.count).toBe(1);
|
|
55
57
|
expect(items.results[0].id).toBe(result.id);
|
|
56
58
|
});
|
|
57
59
|
|
|
58
|
-
test("create customer group with custom fields", () => {
|
|
60
|
+
test("create customer group with custom fields", async () => {
|
|
59
61
|
const draft: CustomerGroupDraft = {
|
|
60
62
|
key: "vip-customers",
|
|
61
63
|
groupName: "VIP Customers",
|
|
@@ -71,7 +73,7 @@ describe("CustomerGroup Repository", () => {
|
|
|
71
73
|
};
|
|
72
74
|
|
|
73
75
|
const ctx = { projectKey: "dummy" };
|
|
74
|
-
const result = repository.create(ctx, draft);
|
|
76
|
+
const result = await repository.create(ctx, draft);
|
|
75
77
|
|
|
76
78
|
expect(result.id).toBeDefined();
|
|
77
79
|
expect(result.key).toBe(draft.key);
|
|
@@ -80,16 +82,16 @@ describe("CustomerGroup Repository", () => {
|
|
|
80
82
|
expect(result.custom?.fields.description).toBe("Very important customers");
|
|
81
83
|
});
|
|
82
84
|
|
|
83
|
-
test("update customer group - changeName", () => {
|
|
85
|
+
test("update customer group - changeName", async () => {
|
|
84
86
|
const draft: CustomerGroupDraft = {
|
|
85
87
|
key: "test-customers",
|
|
86
88
|
groupName: "Test Customers",
|
|
87
89
|
};
|
|
88
90
|
|
|
89
91
|
const ctx = { projectKey: "dummy" };
|
|
90
|
-
const customerGroup = repository.create(ctx, draft);
|
|
92
|
+
const customerGroup = await repository.create(ctx, draft);
|
|
91
93
|
|
|
92
|
-
const result = repository.processUpdateActions(
|
|
94
|
+
const result = await repository.processUpdateActions(
|
|
93
95
|
ctx,
|
|
94
96
|
customerGroup,
|
|
95
97
|
customerGroup.version,
|
|
@@ -105,16 +107,16 @@ describe("CustomerGroup Repository", () => {
|
|
|
105
107
|
expect(result.version).toBe(customerGroup.version + 1);
|
|
106
108
|
});
|
|
107
109
|
|
|
108
|
-
test("update customer group - setKey", () => {
|
|
110
|
+
test("update customer group - setKey", async () => {
|
|
109
111
|
const draft: CustomerGroupDraft = {
|
|
110
112
|
key: "test-customers-2",
|
|
111
113
|
groupName: "Test Customers 2",
|
|
112
114
|
};
|
|
113
115
|
|
|
114
116
|
const ctx = { projectKey: "dummy" };
|
|
115
|
-
const customerGroup = repository.create(ctx, draft);
|
|
117
|
+
const customerGroup = await repository.create(ctx, draft);
|
|
116
118
|
|
|
117
|
-
const result = repository.processUpdateActions(
|
|
119
|
+
const result = await repository.processUpdateActions(
|
|
118
120
|
ctx,
|
|
119
121
|
customerGroup,
|
|
120
122
|
customerGroup.version,
|
|
@@ -130,17 +132,17 @@ describe("CustomerGroup Repository", () => {
|
|
|
130
132
|
expect(result.version).toBe(customerGroup.version + 1);
|
|
131
133
|
});
|
|
132
134
|
|
|
133
|
-
test("update customer group - setCustomType", () => {
|
|
135
|
+
test("update customer group - setCustomType", async () => {
|
|
134
136
|
const draft: CustomerGroupDraft = {
|
|
135
137
|
key: "test-customers-3",
|
|
136
138
|
groupName: "Test Customers 3",
|
|
137
139
|
};
|
|
138
140
|
|
|
139
141
|
const ctx = { projectKey: "dummy" };
|
|
140
|
-
const customerGroup = repository.create(ctx, draft);
|
|
142
|
+
const customerGroup = await repository.create(ctx, draft);
|
|
141
143
|
|
|
142
144
|
// Set custom type
|
|
143
|
-
const result = repository.processUpdateActions(
|
|
145
|
+
const result = await repository.processUpdateActions(
|
|
144
146
|
ctx,
|
|
145
147
|
customerGroup,
|
|
146
148
|
customerGroup.version,
|
|
@@ -163,7 +165,7 @@ describe("CustomerGroup Repository", () => {
|
|
|
163
165
|
expect(result.version).toBe(customerGroup.version + 1);
|
|
164
166
|
|
|
165
167
|
// Remove custom type
|
|
166
|
-
const result2 = repository.processUpdateActions(
|
|
168
|
+
const result2 = await repository.processUpdateActions(
|
|
167
169
|
ctx,
|
|
168
170
|
result,
|
|
169
171
|
result.version,
|
|
@@ -178,7 +180,7 @@ describe("CustomerGroup Repository", () => {
|
|
|
178
180
|
expect(result2.version).toBe(result.version + 1);
|
|
179
181
|
});
|
|
180
182
|
|
|
181
|
-
test("update customer group - setCustomField", () => {
|
|
183
|
+
test("update customer group - setCustomField", async () => {
|
|
182
184
|
const draft: CustomerGroupDraft = {
|
|
183
185
|
key: "test-customers-4",
|
|
184
186
|
groupName: "Test Customers 4",
|
|
@@ -194,10 +196,10 @@ describe("CustomerGroup Repository", () => {
|
|
|
194
196
|
};
|
|
195
197
|
|
|
196
198
|
const ctx = { projectKey: "dummy" };
|
|
197
|
-
const customerGroup = repository.create(ctx, draft);
|
|
199
|
+
const customerGroup = await repository.create(ctx, draft);
|
|
198
200
|
|
|
199
201
|
// Update custom field
|
|
200
|
-
const result = repository.processUpdateActions(
|
|
202
|
+
const result = await repository.processUpdateActions(
|
|
201
203
|
ctx,
|
|
202
204
|
customerGroup,
|
|
203
205
|
customerGroup.version,
|
|
@@ -214,7 +216,7 @@ describe("CustomerGroup Repository", () => {
|
|
|
214
216
|
expect(result.version).toBe(customerGroup.version + 1);
|
|
215
217
|
|
|
216
218
|
// Remove custom field
|
|
217
|
-
const result2 = repository.processUpdateActions(
|
|
219
|
+
const result2 = await repository.processUpdateActions(
|
|
218
220
|
ctx,
|
|
219
221
|
result,
|
|
220
222
|
result.version,
|
|
@@ -231,32 +233,32 @@ describe("CustomerGroup Repository", () => {
|
|
|
231
233
|
expect(result2.version).toBe(result.version + 1);
|
|
232
234
|
});
|
|
233
235
|
|
|
234
|
-
test("get and delete customer group", () => {
|
|
236
|
+
test("get and delete customer group", async () => {
|
|
235
237
|
const draft: CustomerGroupDraft = {
|
|
236
238
|
key: "delete-test",
|
|
237
239
|
groupName: "Delete Test",
|
|
238
240
|
};
|
|
239
241
|
|
|
240
242
|
const ctx = { projectKey: "dummy" };
|
|
241
|
-
const customerGroup = repository.create(ctx, draft);
|
|
243
|
+
const customerGroup = await repository.create(ctx, draft);
|
|
242
244
|
|
|
243
245
|
// Test get
|
|
244
|
-
const retrieved = repository.get(ctx, customerGroup.id);
|
|
246
|
+
const retrieved = await repository.get(ctx, customerGroup.id);
|
|
245
247
|
expect(retrieved).toBeDefined();
|
|
246
248
|
expect(retrieved?.id).toBe(customerGroup.id);
|
|
247
249
|
|
|
248
250
|
// Test getByKey
|
|
249
|
-
const retrievedByKey = repository.getByKey(ctx, customerGroup.key!);
|
|
251
|
+
const retrievedByKey = await repository.getByKey(ctx, customerGroup.key!);
|
|
250
252
|
expect(retrievedByKey).toBeDefined();
|
|
251
253
|
expect(retrievedByKey?.key).toBe(customerGroup.key);
|
|
252
254
|
|
|
253
255
|
// Test delete
|
|
254
|
-
const deleted = repository.delete(ctx, customerGroup.id);
|
|
256
|
+
const deleted = await repository.delete(ctx, customerGroup.id);
|
|
255
257
|
expect(deleted).toBeDefined();
|
|
256
258
|
expect(deleted?.id).toBe(customerGroup.id);
|
|
257
259
|
|
|
258
260
|
// Verify it's deleted
|
|
259
|
-
const notFound = repository.get(ctx, customerGroup.id);
|
|
261
|
+
const notFound = await repository.get(ctx, customerGroup.id);
|
|
260
262
|
expect(notFound).toBeNull();
|
|
261
263
|
});
|
|
262
264
|
});
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
CustomerGroupUpdateAction,
|
|
9
9
|
} from "@commercetools/platform-sdk";
|
|
10
10
|
import type { Config } from "#src/config.ts";
|
|
11
|
+
import { CustomerGroupDraftSchema } from "#src/schemas/generated/customer-group.ts";
|
|
11
12
|
import { getBaseResourceProperties } from "../helpers.ts";
|
|
12
13
|
import type { Writable } from "../types.ts";
|
|
13
14
|
import type { UpdateHandlerInterface } from "./abstract.ts";
|
|
@@ -22,20 +23,24 @@ export class CustomerGroupRepository extends AbstractResourceRepository<"custome
|
|
|
22
23
|
constructor(config: Config) {
|
|
23
24
|
super("customer-group", config);
|
|
24
25
|
this.actions = new CustomerGroupUpdateHandler(config.storage);
|
|
26
|
+
this.draftSchema = CustomerGroupDraftSchema;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
create(
|
|
29
|
+
async create(
|
|
30
|
+
context: RepositoryContext,
|
|
31
|
+
draft: CustomerGroupDraft,
|
|
32
|
+
): Promise<CustomerGroup> {
|
|
28
33
|
const resource: CustomerGroup = {
|
|
29
|
-
...getBaseResourceProperties(),
|
|
34
|
+
...getBaseResourceProperties(context.clientId),
|
|
30
35
|
key: draft.key,
|
|
31
36
|
name: draft.groupName,
|
|
32
|
-
custom: createCustomFields(
|
|
37
|
+
custom: await createCustomFields(
|
|
33
38
|
draft.custom,
|
|
34
39
|
context.projectKey,
|
|
35
40
|
this._storage,
|
|
36
41
|
),
|
|
37
42
|
};
|
|
38
|
-
return this.saveNew(context, resource);
|
|
43
|
+
return await this.saveNew(context, resource);
|
|
39
44
|
}
|
|
40
45
|
}
|
|
41
46
|
|
|
@@ -56,30 +61,15 @@ class CustomerGroupUpdateHandler
|
|
|
56
61
|
resource: Writable<CustomerGroup>,
|
|
57
62
|
{ name, value }: CustomerGroupSetCustomFieldAction,
|
|
58
63
|
) {
|
|
59
|
-
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
if (value === null) {
|
|
63
|
-
delete resource.custom.fields[name];
|
|
64
|
-
} else {
|
|
65
|
-
resource.custom.fields[name] = value;
|
|
66
|
-
}
|
|
64
|
+
this._setCustomFieldValues(resource, { name, value });
|
|
67
65
|
}
|
|
68
66
|
|
|
69
|
-
setCustomType(
|
|
67
|
+
async setCustomType(
|
|
70
68
|
context: RepositoryContext,
|
|
71
69
|
resource: Writable<CustomerGroup>,
|
|
72
70
|
{ type, fields }: CustomerGroupSetCustomTypeAction,
|
|
73
71
|
) {
|
|
74
|
-
|
|
75
|
-
resource.custom = createCustomFields(
|
|
76
|
-
{ type, fields },
|
|
77
|
-
context.projectKey,
|
|
78
|
-
this._storage,
|
|
79
|
-
);
|
|
80
|
-
} else {
|
|
81
|
-
resource.custom = undefined;
|
|
82
|
-
}
|
|
72
|
+
await this._setCustomType(context, resource, { type, fields });
|
|
83
73
|
}
|
|
84
74
|
|
|
85
75
|
setKey(
|
|
@@ -18,7 +18,6 @@ import type {
|
|
|
18
18
|
import type { Writable } from "#src/types.ts";
|
|
19
19
|
import type { UpdateHandlerInterface } from "../abstract.ts";
|
|
20
20
|
import { AbstractUpdateHandler, type RepositoryContext } from "../abstract.ts";
|
|
21
|
-
import { createCustomFields } from "../helpers.ts";
|
|
22
21
|
|
|
23
22
|
export class DiscountCodeUpdateHandler
|
|
24
23
|
extends AbstractUpdateHandler
|
|
@@ -59,30 +58,15 @@ export class DiscountCodeUpdateHandler
|
|
|
59
58
|
resource: Writable<DiscountCode>,
|
|
60
59
|
{ name, value }: DiscountCodeSetCustomFieldAction,
|
|
61
60
|
) {
|
|
62
|
-
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
if (value === null) {
|
|
66
|
-
delete resource.custom.fields[name];
|
|
67
|
-
} else {
|
|
68
|
-
resource.custom.fields[name] = value;
|
|
69
|
-
}
|
|
61
|
+
this._setCustomFieldValues(resource, { name, value });
|
|
70
62
|
}
|
|
71
63
|
|
|
72
|
-
setCustomType(
|
|
64
|
+
async setCustomType(
|
|
73
65
|
context: RepositoryContext,
|
|
74
66
|
resource: Writable<DiscountCode>,
|
|
75
67
|
{ type, fields }: DiscountCodeSetCustomTypeAction,
|
|
76
68
|
) {
|
|
77
|
-
|
|
78
|
-
resource.custom = createCustomFields(
|
|
79
|
-
{ type, fields },
|
|
80
|
-
context.projectKey,
|
|
81
|
-
this._storage,
|
|
82
|
-
);
|
|
83
|
-
} else {
|
|
84
|
-
resource.custom = undefined;
|
|
85
|
-
}
|
|
69
|
+
await this._setCustomType(context, resource, { type, fields });
|
|
86
70
|
}
|
|
87
71
|
|
|
88
72
|
setDescription(
|