@labdigital/commercetools-mock 2.47.0 → 2.48.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/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@labdigital/commercetools-mock",
3
- "version": "2.47.0",
3
+ "version": "2.48.0",
4
4
  "license": "MIT",
5
5
  "author": "Michael van Tellingen",
6
6
  "type": "module",
7
7
  "exports": {
8
8
  ".": {
9
- "require": "./dist/index.cjs",
9
+ "types": "./dist/index.d.ts",
10
10
  "import": "./dist/index.js",
11
- "types": "./dist/index.d.ts"
11
+ "require": "./dist/index.cjs"
12
12
  }
13
13
  },
14
14
  "main": "dist/index.cjs",
@@ -19,47 +19,46 @@
19
19
  "src"
20
20
  ],
21
21
  "dependencies": {
22
- "@biomejs/biome": "^1.9.4",
22
+ "@biomejs/biome": "1.9.4",
23
+ "@types/express": "^5.0.1",
24
+ "@types/express-serve-static-core": "^5.0.6",
23
25
  "basic-auth": "2.0.1",
24
- "body-parser": "1.20.2",
25
- "decimal.js": "10.4.3",
26
+ "body-parser": "2.2.0",
27
+ "decimal.js": "10.5.0",
26
28
  "deep-equal": "2.2.3",
27
- "express": "4.21.1",
28
- "light-my-request": "5.11.1",
29
+ "express": "5.1.0",
30
+ "light-my-request": "6.6.0",
29
31
  "lodash.isequal": "4.5.0",
30
32
  "morgan": "1.10.0",
31
- "msw": "2.5.0",
32
- "uuid": "9.0.1",
33
- "zod": "3.22.4",
34
- "zod-validation-error": "3.0.2"
33
+ "msw": "2.7.3",
34
+ "uuid": "11.1.0",
35
+ "zod": "3.24.2",
36
+ "zod-validation-error": "3.4.0"
35
37
  },
36
38
  "devDependencies": {
37
- "@changesets/changelog-github": "0.5.0",
38
- "@changesets/cli": "2.27.1",
39
+ "@changesets/changelog-github": "0.5.1",
40
+ "@changesets/cli": "2.28.1",
39
41
  "@commercetools/platform-sdk": "8.8.0",
40
42
  "@types/basic-auth": "1.1.8",
41
43
  "@types/body-parser": "1.19.5",
42
44
  "@types/deep-equal": "1.0.4",
43
- "@types/express": "4.17.21",
44
- "@types/express-serve-static-core": "4.17.43",
45
45
  "@types/lodash.isequal": "4.5.8",
46
46
  "@types/morgan": "1.9.9",
47
47
  "@types/node": "20.16.14",
48
48
  "@types/qs": "6.9.11",
49
49
  "@types/supertest": "6.0.2",
50
50
  "@types/uuid": "9.0.8",
51
- "@vitest/coverage-v8": "3.0.2",
52
- "esbuild": "0.20.1",
53
- "fishery": "2.2.2",
51
+ "@vitest/coverage-v8": "3.1.1",
52
+ "esbuild": "0.25.2",
53
+ "fishery": "2.2.3",
54
54
  "got": "14.2.0",
55
- "husky": "9.0.11",
56
- "supertest": "6.3.4",
55
+ "husky": "9.1.7",
56
+ "supertest": "7.1.0",
57
57
  "timekeeper": "2.3.1",
58
- "ts-node": "10.9.2",
59
- "tslib": "2.8.0",
60
- "tsup": "8.0.2",
58
+ "tslib": "2.8.1",
59
+ "tsup": "8.4.0",
61
60
  "typescript": "5.8.3",
62
- "vitest": "3.0.2"
61
+ "vitest": "3.1.1"
63
62
  },
64
63
  "engines": {
65
64
  "node": ">=18",
package/src/ctMock.ts CHANGED
@@ -170,23 +170,26 @@ export class CommercetoolsMock {
170
170
  app.use((err: Error, req: Request, resp: Response, next: NextFunction) => {
171
171
  if (err instanceof CommercetoolsError) {
172
172
  if (err.errors?.length > 0) {
173
- return resp.status(err.statusCode).send({
173
+ resp.status(err.statusCode).send({
174
174
  statusCode: err.statusCode,
175
175
  message: err.message,
176
176
  errors: err.errors,
177
177
  });
178
+ return;
178
179
  }
179
180
 
180
- return resp.status(err.statusCode).send({
181
+ resp.status(err.statusCode).send({
181
182
  statusCode: err.statusCode,
182
183
  message: err.message,
183
184
  errors: [err.info],
184
185
  });
186
+ return;
185
187
  }
186
188
  console.error(err);
187
- return resp.status(500).send({
189
+ resp.status(500).send({
188
190
  error: err.message,
189
191
  });
192
+ return;
190
193
  });
191
194
 
192
195
  return app;
@@ -39,6 +39,14 @@ describe("OAuth2Server", () => {
39
39
 
40
40
  expect(response.status, JSON.stringify(body)).toBe(200);
41
41
  expect(body).toHaveProperty("access_token");
42
+ expect(body).toEqual({
43
+ // scope: expect.stringMatching(/anonymous_id:([^\s]+)/),
44
+ scope: expect.any(String),
45
+ access_token: expect.stringMatching(/\S{8,}==$/),
46
+ refresh_token: expect.stringMatching(/my-project.*/),
47
+ expires_in: 172800,
48
+ token_type: "Bearer",
49
+ });
42
50
  });
43
51
 
44
52
  it("should failed on invalid refresh token", async () => {
@@ -160,7 +160,7 @@ export class OAuth2Server {
160
160
  );
161
161
  }
162
162
 
163
- const grantType = request.query.grant_type || request.body.grant_type;
163
+ const grantType = request.query.grant_type || request.body?.grant_type;
164
164
  if (!grantType) {
165
165
  return next(
166
166
  new CommercetoolsError<InvalidRequestError>(
@@ -179,11 +179,12 @@ export class OAuth2Server {
179
179
  request.credentials.clientSecret,
180
180
  request.query.scope?.toString(),
181
181
  );
182
- return response.status(200).send(token);
182
+ response.status(200).send(token);
183
+ return;
183
184
  }
184
185
  if (grantType === "refresh_token") {
185
186
  const refreshToken =
186
- request.query.refresh_token?.toString() || request.body.refresh_token;
187
+ request.query.refresh_token?.toString() || request.body?.refresh_token;
187
188
  if (!refreshToken) {
188
189
  return next(
189
190
  new CommercetoolsError<InvalidRequestError>(
@@ -214,7 +215,8 @@ export class OAuth2Server {
214
215
  ),
215
216
  );
216
217
  }
217
- return response.status(200).send(token);
218
+ response.status(200).send(token);
219
+ return;
218
220
  }
219
221
  return next(
220
222
  new CommercetoolsError<UnsupportedGrantType>(
@@ -233,7 +235,7 @@ export class OAuth2Server {
233
235
  next: NextFunction,
234
236
  ) {
235
237
  const projectKey = request.params.projectKey;
236
- const grantType = request.query.grant_type || request.body.grant_type;
238
+ const grantType = request.query.grant_type || request.body?.grant_type;
237
239
  if (!grantType) {
238
240
  return next(
239
241
  new CommercetoolsError<InvalidRequestError>(
@@ -247,12 +249,12 @@ export class OAuth2Server {
247
249
  }
248
250
 
249
251
  if (grantType === "password") {
250
- const username = request.query.username || request.body.username;
252
+ const username = request.query.username || request.body?.username;
251
253
  const password = hashPassword(
252
254
  request.query.password || request.body.password,
253
255
  );
254
256
  const scope =
255
- request.query.scope?.toString() || request.body.scope?.toString();
257
+ request.query.scope?.toString() || request.body?.scope?.toString();
256
258
 
257
259
  const result = this.customerRepository.query(
258
260
  { projectKey: request.params.projectKey },
@@ -275,7 +277,7 @@ export class OAuth2Server {
275
277
 
276
278
  const customer = result.results[0];
277
279
  const token = this.store.getCustomerToken(projectKey, customer.id, scope);
278
- return response.status(200).send(token);
280
+ response.status(200).send(token);
279
281
  }
280
282
  }
281
283
 
@@ -328,7 +330,8 @@ export class OAuth2Server {
328
330
 
329
331
  const customer = result.results[0];
330
332
  const token = this.store.getCustomerToken(projectKey, customer.id, scope);
331
- return response.status(200).send(token);
333
+ response.status(200).send(token);
334
+ return;
332
335
  }
333
336
  }
334
337
 
@@ -353,7 +356,7 @@ export class OAuth2Server {
353
356
 
354
357
  if (grantType === "client_credentials") {
355
358
  const scope =
356
- request.query.scope?.toString() || request.body.scope?.toString();
359
+ request.query.scope?.toString() || request.body?.scope?.toString();
357
360
 
358
361
  const anonymous_id = undefined;
359
362
 
@@ -362,7 +365,8 @@ export class OAuth2Server {
362
365
  anonymous_id,
363
366
  scope,
364
367
  );
365
- return response.status(200).send(token);
368
+ response.status(200).send(token);
369
+ return;
366
370
  }
367
371
  }
368
372
  }
@@ -1,5 +1,7 @@
1
1
  import { CartRepository } from "./cart";
2
2
  import { OrderRepository } from "./order";
3
+ import { QuoteRequestRepository } from "./quote-request";
3
4
 
4
5
  export class AsAssociateOrderRepository extends OrderRepository {}
5
6
  export class AsAssociateCartRepository extends CartRepository {}
7
+ export class AsAssociateQuoteRequestRepository extends QuoteRequestRepository {}
@@ -3,6 +3,7 @@ import { ProductTailoringRepository } from "~src/repositories/product-tailoring"
3
3
  import {
4
4
  AsAssociateCartRepository,
5
5
  AsAssociateOrderRepository,
6
+ AsAssociateQuoteRequestRepository,
6
7
  } from "./as-associate";
7
8
  import { AssociateRoleRepository } from "./associate-role";
8
9
  import { AttributeGroupRepository } from "./attribute-group";
@@ -48,6 +49,7 @@ export const createRepositories = (config: Config) => ({
48
49
  "as-associate": {
49
50
  cart: new AsAssociateCartRepository(config),
50
51
  order: new AsAssociateOrderRepository(config),
52
+ "quote-request": new AsAssociateQuoteRequestRepository(config),
51
53
  },
52
54
  "associate-role": new AssociateRoleRepository(config),
53
55
  "attribute-group": new AttributeGroupRepository(config),
@@ -0,0 +1,3 @@
1
+ import { QuoteRequestRepository } from "./quote-request";
2
+
3
+ export class MyQuoteRequestRepository extends QuoteRequestRepository {}
@@ -2,6 +2,7 @@ import assert from "node:assert";
2
2
  import type {
3
3
  Cart,
4
4
  CartReference,
5
+ MyQuoteRequestDraft,
5
6
  QuoteRequest,
6
7
  QuoteRequestDraft,
7
8
  } from "@commercetools/platform-sdk";
@@ -17,7 +18,18 @@ export class QuoteRequestRepository extends AbstractResourceRepository<"quote-re
17
18
  this.actions = new QuoteRequestUpdateHandler(config.storage);
18
19
  }
19
20
 
20
- create(context: RepositoryContext, draft: QuoteRequestDraft): QuoteRequest {
21
+ create(
22
+ context: RepositoryContext,
23
+ draft: QuoteRequestDraft | MyQuoteRequestDraft,
24
+ ): QuoteRequest {
25
+ // Handle the 'my' version of the draft
26
+ if ("cartId" in draft) {
27
+ return this.createFromCart(context, {
28
+ id: draft.cartId,
29
+ typeId: "cart",
30
+ });
31
+ }
32
+
21
33
  assert(draft.cart, "draft.cart is missing");
22
34
  return this.createFromCart(context, {
23
35
  id: draft.cart.id!,
@@ -64,15 +64,26 @@ export default abstract class AbstractService {
64
64
  }
65
65
 
66
66
  const result = this.repository.query(getRepositoryContext(request), params);
67
- return response.status(200).send(result);
67
+ response.status(200).send(result);
68
+ return;
68
69
  }
69
70
 
70
71
  getWithId(request: Request, response: Response) {
71
72
  const result = this._expandWithId(request, request.params.id);
72
73
  if (!result) {
73
- return response.status(404).send();
74
+ response.status(404).send({
75
+ statusCode: 404,
76
+ message: `The Resource with ID '${request.params.id} was not found.`,
77
+ errors: [
78
+ {
79
+ code: "ResourceNotFound",
80
+ message: `The Resource with ID '${request.params.id} was not found.`,
81
+ },
82
+ ],
83
+ });
84
+ return;
74
85
  }
75
- return response.status(200).send(result);
86
+ response.status(200).send(result);
76
87
  }
77
88
 
78
89
  getWithKey(request: Request, response: Response) {
@@ -83,8 +94,20 @@ export default abstract class AbstractService {
83
94
  expand: this._parseParam(request.query.expand),
84
95
  },
85
96
  );
86
- if (!result) return response.status(404).send();
87
- return response.status(200).send(result);
97
+ if (!result) {
98
+ response.status(404).send({
99
+ statusCode: 404,
100
+ message: `The Resource with key '${request.params.id} was not found.`,
101
+ errors: [
102
+ {
103
+ code: "ResourceNotFound",
104
+ message: `The Resource with key '${request.params.id} was not found.`,
105
+ },
106
+ ],
107
+ });
108
+ return;
109
+ }
110
+ response.status(200).send(result);
88
111
  }
89
112
 
90
113
  deleteWithId(request: Request, response: Response) {
@@ -96,9 +119,10 @@ export default abstract class AbstractService {
96
119
  },
97
120
  );
98
121
  if (!result) {
99
- return response.status(404).send("Not found");
122
+ response.sendStatus(404);
123
+ return;
100
124
  }
101
- return response.status(200).send(result);
125
+ response.status(200).send(result);
102
126
  }
103
127
 
104
128
  deleteWithKey(request: Request, response: Response) {
@@ -107,7 +131,8 @@ export default abstract class AbstractService {
107
131
  request.params.key,
108
132
  );
109
133
  if (!resource) {
110
- return response.status(404).send("Not found");
134
+ response.sendStatus(404);
135
+ return;
111
136
  }
112
137
 
113
138
  const result = this.repository.delete(
@@ -118,9 +143,10 @@ export default abstract class AbstractService {
118
143
  },
119
144
  );
120
145
  if (!result) {
121
- return response.status(404).send("Not found");
146
+ response.sendStatus(404);
147
+ return;
122
148
  }
123
- return response.status(200).send(result);
149
+ response.status(200).send(result);
124
150
  }
125
151
 
126
152
  post(request: Request, response: Response) {
@@ -130,7 +156,7 @@ export default abstract class AbstractService {
130
156
  draft,
131
157
  );
132
158
  const result = this._expandWithId(request, resource.id);
133
- return response.status(this.createStatusCode).send(result);
159
+ response.status(this.createStatusCode).send(result);
134
160
  }
135
161
 
136
162
  postWithId(request: Request, response: Response) {
@@ -143,7 +169,8 @@ export default abstract class AbstractService {
143
169
  request.params.id,
144
170
  );
145
171
  if (!resource) {
146
- return response.status(404).send("Not found");
172
+ response.sendStatus(404);
173
+ return;
147
174
  }
148
175
 
149
176
  const updatedResource = this.repository.processUpdateActions(
@@ -154,7 +181,7 @@ export default abstract class AbstractService {
154
181
  );
155
182
 
156
183
  const result = this._expandWithId(request, updatedResource.id);
157
- return response.status(200).send(result);
184
+ response.status(200).send(result);
158
185
  }
159
186
 
160
187
  postWithKey(request: Request, response: Response) {
@@ -168,7 +195,8 @@ export default abstract class AbstractService {
168
195
  request.params.key,
169
196
  );
170
197
  if (!resource) {
171
- return response.status(404).send("Not found");
198
+ response.sendStatus(404);
199
+ return;
172
200
  }
173
201
 
174
202
  const updatedResource = this.repository.processUpdateActions(
@@ -179,7 +207,7 @@ export default abstract class AbstractService {
179
207
  );
180
208
 
181
209
  const result = this._expandWithId(request, updatedResource.id);
182
- return response.status(200).send(result);
210
+ response.status(200).send(result);
183
211
  }
184
212
 
185
213
  protected _expandWithId(request: Request, resourceId: string) {
@@ -0,0 +1,34 @@
1
+ import { Router } from "express";
2
+ import type { MyQuoteRequestRepository } from "~src/repositories/my-quote-request";
3
+ import type { MyOrderRepository } from "../repositories/my-order";
4
+ import AbstractService from "./abstract";
5
+
6
+ export class AsAssociateQuoteRequestService extends AbstractService {
7
+ public repository: MyQuoteRequestRepository;
8
+
9
+ constructor(parent: Router, repository: MyQuoteRequestRepository) {
10
+ super(parent);
11
+ this.repository = repository;
12
+ }
13
+
14
+ getBasePath() {
15
+ return "quote-requests";
16
+ }
17
+
18
+ registerRoutes(parent: Router) {
19
+ const basePath = this.getBasePath();
20
+ const router = Router({ mergeParams: true });
21
+
22
+ this.extraRoutes(router);
23
+
24
+ router.get("/", this.get.bind(this));
25
+ router.get("/:id", this.getWithId.bind(this));
26
+
27
+ router.delete("/:id", this.deleteWithId.bind(this));
28
+
29
+ router.post("/", this.post.bind(this));
30
+ router.post("/:id", this.postWithId.bind(this));
31
+
32
+ parent.use(`/${basePath}`, router);
33
+ }
34
+ }
@@ -2,13 +2,16 @@ import { Router } from "express";
2
2
  import type {
3
3
  AsAssociateCartRepository,
4
4
  AsAssociateOrderRepository,
5
+ AsAssociateQuoteRequestRepository,
5
6
  } from "~src/repositories/as-associate";
6
7
  import { AsAssociateCartService } from "./as-associate-cart";
7
8
  import { AsAssociateOrderService } from "./as-associate-order";
9
+ import { AsAssociateQuoteRequestService } from "./as-associate-quote-request";
8
10
 
9
11
  type Repositories = {
10
12
  cart: AsAssociateCartRepository;
11
13
  order: AsAssociateOrderRepository;
14
+ "quote-request": AsAssociateQuoteRequestRepository;
12
15
  };
13
16
 
14
17
  export class AsAssociateService {
@@ -17,6 +20,7 @@ export class AsAssociateService {
17
20
  subServices: {
18
21
  cart: AsAssociateCartService;
19
22
  order: AsAssociateOrderService;
23
+ "quote-request": AsAssociateQuoteRequestService;
20
24
  };
21
25
 
22
26
  constructor(parent: Router, repositories: Repositories) {
@@ -25,6 +29,10 @@ export class AsAssociateService {
25
29
  this.subServices = {
26
30
  order: new AsAssociateOrderService(this.router, repositories.order),
27
31
  cart: new AsAssociateCartService(this.router, repositories.cart),
32
+ "quote-request": new AsAssociateQuoteRequestService(
33
+ this.router,
34
+ repositories["quote-request"],
35
+ ),
28
36
  };
29
37
  parent.use(
30
38
  "/as-associate/:associateId/in-business-unit/key=:businessUnitId",
@@ -38,7 +38,8 @@ export class CartService extends AbstractService {
38
38
  : this.repository.get(context, request.body.reference.id);
39
39
 
40
40
  if (!cartOrOrder) {
41
- return response.status(400).send();
41
+ response.status(400).send();
42
+ return;
42
43
  }
43
44
 
44
45
  const cartDraft: CartDraft = {
@@ -55,6 +56,6 @@ export class CartService extends AbstractService {
55
56
 
56
57
  const newCart = this.repository.create(context, cartDraft);
57
58
 
58
- return response.status(200).send(newCart);
59
+ response.status(200).send(newCart);
59
60
  }
60
61
  }
@@ -41,7 +41,7 @@ export class CustomObjectService extends AbstractService {
41
41
  },
42
42
  );
43
43
 
44
- return response.status(200).send(result);
44
+ response.status(200).send(result);
45
45
  }
46
46
 
47
47
  getWithContainerAndKey(request: Request, response: Response) {
@@ -52,9 +52,10 @@ export class CustomObjectService extends AbstractService {
52
52
  );
53
53
 
54
54
  if (!result) {
55
- return response.status(404).send("Not Found");
55
+ response.sendStatus(404);
56
+ return;
56
57
  }
57
- return response.status(200).send(result);
58
+ response.status(200).send(result);
58
59
  }
59
60
 
60
61
  createWithContainerAndKey(request: Request, response: Response) {
@@ -65,7 +66,7 @@ export class CustomObjectService extends AbstractService {
65
66
  };
66
67
 
67
68
  const result = this.repository.create(getRepositoryContext(request), draft);
68
- return response.status(200).send(result);
69
+ response.status(200).send(result);
69
70
  }
70
71
 
71
72
  deleteWithContainerAndKey(request: Request, response: Response) {
@@ -76,7 +77,8 @@ export class CustomObjectService extends AbstractService {
76
77
  );
77
78
 
78
79
  if (!current) {
79
- return response.status(404).send("Not Found");
80
+ response.sendStatus(404);
81
+ return;
80
82
  }
81
83
 
82
84
  const result = this.repository.delete(
@@ -84,6 +86,6 @@ export class CustomObjectService extends AbstractService {
84
86
  current.id,
85
87
  );
86
88
 
87
- return response.status(200).send(result);
89
+ response.status(200).send(result);
88
90
  }
89
91
  }
@@ -34,7 +34,7 @@ export class CustomerService extends AbstractService {
34
34
  const result: CustomerSignInResult = {
35
35
  customer: expanded,
36
36
  };
37
- return response.status(this.createStatusCode).send(result);
37
+ response.status(this.createStatusCode).send(result);
38
38
  }
39
39
 
40
40
  passwordResetToken(request: Request, response: Response) {
@@ -43,7 +43,7 @@ export class CustomerService extends AbstractService {
43
43
  request.body,
44
44
  );
45
45
 
46
- return response.status(200).send(customer);
46
+ response.status(200).send(customer);
47
47
  }
48
48
 
49
49
  passwordReset(request: Request, response: Response) {
@@ -52,7 +52,7 @@ export class CustomerService extends AbstractService {
52
52
  request.body,
53
53
  );
54
54
 
55
- return response.status(200).send(customer);
55
+ response.status(200).send(customer);
56
56
  }
57
57
 
58
58
  confirmEmailToken(request: Request, response: Response) {
@@ -61,6 +61,6 @@ export class CustomerService extends AbstractService {
61
61
  getRepositoryContext(request),
62
62
  id,
63
63
  );
64
- return response.status(200).send(token);
64
+ response.status(200).send(token);
65
65
  }
66
66
  }
@@ -37,8 +37,9 @@ export class MyCartService extends AbstractService {
37
37
  activeCart(request: Request, response: Response) {
38
38
  const resource = this.repository.getActiveCart(request.params.projectKey);
39
39
  if (!resource) {
40
- return response.status(404).send("Not found");
40
+ response.sendStatus(404);
41
+ return;
41
42
  }
42
- return response.status(200).send(resource);
43
+ response.status(200).send(resource);
43
44
  }
44
45
  }