@mamindom/common 1.0.122 → 1.0.123

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.
@@ -47,9 +47,14 @@ export declare const GRPC_CLIENTS: {
47
47
  };
48
48
  readonly CART_PACKAGE: {
49
49
  readonly package: "cart.v1";
50
- readonly protoPath: readonly [string];
50
+ readonly protoPath: readonly [string, string];
51
51
  readonly env: "CART_GRPC_URL";
52
52
  };
53
+ readonly CRM_PACKAGE: {
54
+ readonly package: "crm.v1";
55
+ readonly protoPath: readonly [string];
56
+ readonly env: "INTEGRATION_GRPC_URL";
57
+ };
53
58
  readonly ORDER_PACKAGE: {
54
59
  readonly package: "order.v1";
55
60
  readonly protoPath: readonly [string];
@@ -84,9 +84,14 @@ exports.GRPC_CLIENTS = {
84
84
  },
85
85
  CART_PACKAGE: {
86
86
  package: 'cart.v1',
87
- protoPath: [contracts_1.PROTO_PATHS.CART],
87
+ protoPath: [contracts_1.PROTO_PATHS.CART, contracts_1.PROTO_PATHS.CRM_CALCULATION],
88
88
  env: 'CART_GRPC_URL'
89
89
  },
90
+ CRM_PACKAGE: {
91
+ package: 'crm.v1',
92
+ protoPath: [contracts_1.PROTO_PATHS.CRM_CALCULATION],
93
+ env: 'INTEGRATION_GRPC_URL'
94
+ },
90
95
  ORDER_PACKAGE: {
91
96
  package: 'order.v1',
92
97
  protoPath: [contracts_1.PROTO_PATHS.ORDER],
@@ -78,6 +78,11 @@ exports.PERMISSION_GROUPS = [
78
78
  key: 'orders.assign',
79
79
  groupKey: 'orders',
80
80
  label: 'Призначення менеджера'
81
+ },
82
+ {
83
+ key: 'orders.pickup.confirm',
84
+ groupKey: 'orders',
85
+ label: 'Підтвердження видачі самовивозу'
81
86
  }
82
87
  ]
83
88
  },
@@ -303,6 +308,7 @@ exports.SYSTEM_ROLE_DEFAULTS = {
303
308
  'orders.cancel',
304
309
  'orders.refund',
305
310
  'orders.assign',
311
+ 'orders.pickup.confirm',
306
312
  'customers.view',
307
313
  'customers.edit',
308
314
  'customers.notify',
@@ -1,37 +1,12 @@
1
- /**
2
- * Convention: dead-letter exchange and queue names are derived from the
3
- * primary queue name. `cart_queue` → `cart.dlx` + `cart.dlq`. The `_queue`
4
- * or `-queue` suffix is stripped; if absent, the whole name is used.
5
- *
6
- * Keeping this as a pure function (instead of env vars) prevents the class
7
- * of bugs where producer and consumer disagree on DLX naming and trigger
8
- * PRECONDITION_FAILED on queue declare.
9
- */
10
1
  export declare function dlxNameFor(queue: string): string;
11
2
  export declare function dlqNameFor(queue: string): string;
12
- /**
13
- * queueOptions.arguments needed for a queue that should dead-letter into its
14
- * conventional DLX. Use in `app.connectMicroservice(...)` and in every
15
- * `ClientsModule.registerAsync` that declares the same queue, so producer
16
- * and consumer declares stay equivalent.
17
- */
18
3
  export declare function rmqQueueDlxArguments(queue: string): {
19
4
  'x-dead-letter-exchange': string;
20
5
  };
21
6
  export interface BootstrapRmqDlxOptions {
22
7
  url: string;
23
8
  queue: string;
9
+ maxAttempts?: number;
10
+ retryDelayMs?: number;
24
11
  }
25
- /**
26
- * Idempotently declares the DLX trio for the given queue: fanout exchange +
27
- * DLQ queue + binding. Run once at service bootstrap, before connecting RMQ
28
- * microservice. Safe to repeat — RabbitMQ no-ops on identical re-declares.
29
- *
30
- * `amqplib` is loaded lazily so services that import other helpers from this
31
- * module but don't actually run RMQ (e.g. gateway-service) don't need amqplib
32
- * in their node_modules.
33
- *
34
- * Why fanout: dead-lettered messages keep their original routing key, but
35
- * we want every message into the DLX to land in the DLQ regardless of key.
36
- */
37
12
  export declare function bootstrapRmqDlx(opts: BootstrapRmqDlxOptions): Promise<void>;
@@ -5,15 +5,6 @@ exports.dlqNameFor = dlqNameFor;
5
5
  exports.rmqQueueDlxArguments = rmqQueueDlxArguments;
6
6
  exports.bootstrapRmqDlx = bootstrapRmqDlx;
7
7
  const common_1 = require("@nestjs/common");
8
- /**
9
- * Convention: dead-letter exchange and queue names are derived from the
10
- * primary queue name. `cart_queue` → `cart.dlx` + `cart.dlq`. The `_queue`
11
- * or `-queue` suffix is stripped; if absent, the whole name is used.
12
- *
13
- * Keeping this as a pure function (instead of env vars) prevents the class
14
- * of bugs where producer and consumer disagree on DLX naming and trigger
15
- * PRECONDITION_FAILED on queue declare.
16
- */
17
8
  function dlxNameFor(queue) {
18
9
  return `${stripQueueSuffix(queue)}.dlx`;
19
10
  }
@@ -23,34 +14,30 @@ function dlqNameFor(queue) {
23
14
  function stripQueueSuffix(queue) {
24
15
  return queue.replace(/[_-]queue$/, '');
25
16
  }
26
- /**
27
- * queueOptions.arguments needed for a queue that should dead-letter into its
28
- * conventional DLX. Use in `app.connectMicroservice(...)` and in every
29
- * `ClientsModule.registerAsync` that declares the same queue, so producer
30
- * and consumer declares stay equivalent.
31
- */
32
17
  function rmqQueueDlxArguments(queue) {
33
18
  return { 'x-dead-letter-exchange': dlxNameFor(queue) };
34
19
  }
35
- /**
36
- * Idempotently declares the DLX trio for the given queue: fanout exchange +
37
- * DLQ queue + binding. Run once at service bootstrap, before connecting RMQ
38
- * microservice. Safe to repeat — RabbitMQ no-ops on identical re-declares.
39
- *
40
- * `amqplib` is loaded lazily so services that import other helpers from this
41
- * module but don't actually run RMQ (e.g. gateway-service) don't need amqplib
42
- * in their node_modules.
43
- *
44
- * Why fanout: dead-lettered messages keep their original routing key, but
45
- * we want every message into the DLX to land in the DLQ regardless of key.
46
- */
47
20
  async function bootstrapRmqDlx(opts) {
48
21
  const logger = new common_1.Logger('RmqDlxBootstrap');
49
22
  const dlx = dlxNameFor(opts.queue);
50
23
  const dlq = dlqNameFor(opts.queue);
51
24
  // eslint-disable-next-line @typescript-eslint/no-require-imports
52
25
  const amqp = require('amqplib');
53
- const connection = await amqp.connect(opts.url);
26
+ const maxAttempts = opts.maxAttempts ?? 60;
27
+ const retryDelayMs = opts.retryDelayMs ?? 5000;
28
+ let connection;
29
+ for (let attempt = 1; connection === undefined; attempt++) {
30
+ try {
31
+ connection = await amqp.connect(opts.url);
32
+ }
33
+ catch (err) {
34
+ if (attempt >= maxAttempts) {
35
+ throw err;
36
+ }
37
+ logger.warn(`RMQ connect failed (attempt ${String(attempt)}/${String(maxAttempts)}), retrying in ${String(retryDelayMs)}ms: ${err instanceof Error ? err.message : String(err)}`);
38
+ await new Promise(resolve => setTimeout(resolve, retryDelayMs));
39
+ }
40
+ }
54
41
  try {
55
42
  const channel = await connection.createChannel();
56
43
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mamindom/common",
3
- "version": "1.0.122",
3
+ "version": "1.0.123",
4
4
  "type": "commonjs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  "typescript": "^5.9.3"
24
24
  },
25
25
  "dependencies": {
26
- "@mamindom/contracts": "^1.0.152",
26
+ "@mamindom/contracts": "^1.0.154",
27
27
  "@nestjs/common": "^11.1.16",
28
28
  "@nestjs/config": "^4.0.3",
29
29
  "@nestjs/microservices": "^11.1.16"