@seidor-cloud-produtos/orbit-backend-lib 2.0.110 → 2.0.111

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/clean-arch/application/cache/cache.spec.d.ts +1 -0
  2. package/dist/clean-arch/application/cache/cache.spec.js +178 -0
  3. package/dist/clean-arch/application/consistency-event-dispatcher/consistency-event-dispatcher.d.ts +1 -1
  4. package/dist/clean-arch/application/logger/logger.spec.d.ts +1 -0
  5. package/dist/clean-arch/application/logger/logger.spec.js +204 -0
  6. package/dist/clean-arch/domain/entities/entity.spec.d.ts +1 -0
  7. package/dist/clean-arch/domain/entities/entity.spec.js +130 -0
  8. package/dist/clean-arch/domain/events/consistency-event/consistency-event.spec.d.ts +1 -0
  9. package/dist/clean-arch/domain/events/consistency-event/consistency-event.spec.js +91 -0
  10. package/dist/clean-arch/domain/value-objects/password.spec.d.ts +1 -0
  11. package/dist/clean-arch/domain/value-objects/password.spec.js +90 -0
  12. package/dist/clean-arch/infra/adapters/http-adapters.spec.d.ts +1 -0
  13. package/dist/clean-arch/infra/adapters/http-adapters.spec.js +318 -0
  14. package/dist/clean-arch/infra/authorizations/authorizer.spec.js +43 -0
  15. package/dist/clean-arch/infra/cache/cache-clients.spec.d.ts +1 -0
  16. package/dist/clean-arch/infra/cache/cache-clients.spec.js +161 -0
  17. package/dist/clean-arch/infra/cache/clients/node-cache.js +3 -2
  18. package/dist/clean-arch/infra/http/controller.spec.js +170 -51
  19. package/dist/clean-arch/infra/http/helpers.spec.d.ts +1 -0
  20. package/dist/clean-arch/infra/http/helpers.spec.js +136 -0
  21. package/dist/clean-arch/infra/http/net.spec.d.ts +1 -0
  22. package/dist/clean-arch/infra/http/net.spec.js +46 -0
  23. package/dist/clean-arch/infra/logger/logger-orbit.d.ts +2 -0
  24. package/dist/clean-arch/infra/logger/logger-orbit.spec.d.ts +1 -0
  25. package/dist/clean-arch/infra/logger/logger-orbit.spec.js +122 -0
  26. package/dist/clean-arch/infra/orbit-http-client/orbit-axios-client/orbit-axios-client.spec.d.ts +1 -0
  27. package/dist/clean-arch/infra/orbit-http-client/orbit-axios-client/orbit-axios-client.spec.js +143 -0
  28. package/dist/clean-arch/infra/orbit-notification-client/discord-client.spec.d.ts +1 -0
  29. package/dist/clean-arch/infra/orbit-notification-client/discord-client.spec.js +58 -0
  30. package/dist/clean-arch/infra/queue/queue-utils.spec.d.ts +1 -0
  31. package/dist/clean-arch/infra/queue/queue-utils.spec.js +170 -0
  32. package/dist/clean-arch/infra/queue/rabbitmq/amqp-lib.js +4 -4
  33. package/dist/clean-arch/infra/queue/rabbitmq/amqp-lib.spec.js +466 -89
  34. package/dist/clean-arch/infra/queue/rabbitmq/types.d.ts +1 -1
  35. package/dist/clean-arch/infra/scaledjob/amqp/runner.d.ts +0 -3
  36. package/dist/clean-arch/infra/scaledjob/amqp/runner.js +5 -6
  37. package/dist/clean-arch/infra/scaledjob/amqp/runner.spec.js +74 -84
  38. package/dist/clean-arch/infra/scaledjob/sqs/runner.spec.d.ts +1 -0
  39. package/dist/clean-arch/infra/scaledjob/sqs/runner.spec.js +150 -0
  40. package/dist/clean-arch/infra/tracing/start-tracing.d.ts +10 -0
  41. package/dist/clean-arch/infra/tracing/start-tracing.js +78 -0
  42. package/dist/clean-arch/infra/validations/zod/validation-zod.spec.js +23 -0
  43. package/dist/clean-arch/shared/pagination/get-take-and-skip.spec.d.ts +1 -0
  44. package/dist/clean-arch/shared/pagination/get-take-and-skip.spec.js +16 -0
  45. package/dist/coverage/block-navigation.d.ts +1 -0
  46. package/dist/coverage/block-navigation.js +72 -0
  47. package/dist/coverage/prettify.d.ts +0 -0
  48. package/dist/coverage/prettify.js +1009 -0
  49. package/dist/coverage/sorter.d.ts +1 -0
  50. package/dist/coverage/sorter.js +178 -0
  51. package/dist/frameworks/express/api-gateway/mapping-model.spec.js +58 -0
  52. package/dist/frameworks/express/authorizations/authorization-express.spec.js +9 -0
  53. package/dist/frameworks/express/middleware-express.spec.d.ts +1 -0
  54. package/dist/frameworks/express/middleware-express.spec.js +51 -0
  55. package/dist/frameworks/nest/nest.spec.d.ts +1 -0
  56. package/dist/frameworks/nest/nest.spec.js +122 -0
  57. package/dist/infra/http/api-gateway/mapping-model.spec.js +42 -0
  58. package/package.json +5 -1
@@ -5,123 +5,113 @@ const runner_1 = require("./runner");
5
5
  (0, vitest_1.describe)('RabbitMQScaledJobRunner', () => {
6
6
  let amqpQueue;
7
7
  let handler;
8
- let options;
9
- let onFinally;
10
- let runner;
8
+ let logger;
11
9
  (0, vitest_1.beforeEach)(() => {
12
10
  amqpQueue = {
13
- connect: vitest_1.vi.fn().mockResolvedValue(undefined),
14
- get: vitest_1.vi.fn().mockResolvedValue(null),
11
+ get: vitest_1.vi.fn(),
15
12
  ack: vitest_1.vi.fn().mockResolvedValue(undefined),
16
13
  nack: vitest_1.vi.fn().mockResolvedValue(undefined),
17
14
  close: vitest_1.vi.fn().mockResolvedValue(undefined),
18
15
  };
19
- handler = { handle: vitest_1.vi.fn().mockResolvedValue(undefined) };
20
- options = {
21
- manualAck: true,
22
- timeoutMs: 1000,
23
- errorStrategy: 'nack-dlq',
24
- parse: vitest_1.vi.fn((raw) => ({ ok: true, msg: 'parsed' })),
16
+ handler = {
17
+ handle: vitest_1.vi.fn().mockResolvedValue(undefined),
18
+ getSimultaneity: vitest_1.vi.fn().mockReturnValue(1),
19
+ getTimeoutPerMessageSeconds: vitest_1.vi.fn().mockReturnValue(undefined),
25
20
  };
26
- onFinally = vitest_1.vi.fn();
27
- runner = new runner_1.RabbitMQScaledJobRunner(amqpQueue, 'queue', handler, options);
21
+ logger = {
22
+ info: vitest_1.vi.fn(),
23
+ warn: vitest_1.vi.fn(),
24
+ error: vitest_1.vi.fn(),
25
+ debug: vitest_1.vi.fn(),
26
+ };
27
+ vitest_1.vi.spyOn(process, 'exit').mockImplementation((() => undefined));
28
+ });
29
+ (0, vitest_1.afterEach)(() => {
30
+ vitest_1.vi.useRealTimers();
31
+ vitest_1.vi.restoreAllMocks();
28
32
  });
29
- (0, vitest_1.it)('should connect, get, handle, ack and close (happy path)', async () => {
30
- const rawMessage = { content: Buffer.from('msg') };
33
+ const makeRunner = (options) => new runner_1.RabbitMQScaledJobRunner(amqpQueue, 'queue', handler, options, logger);
34
+ (0, vitest_1.it)('should connect the polling flow, parse the message, ack and close', async () => {
35
+ const rawMessage = { content: Buffer.from(JSON.stringify({ id: '1' })) };
31
36
  const channel = {};
37
+ const runner = makeRunner();
32
38
  amqpQueue.get.mockResolvedValue({ channel, rawMessage });
33
39
  await runner.run();
34
- (0, vitest_1.expect)(amqpQueue.connect).toHaveBeenCalledWith('vhost');
35
40
  (0, vitest_1.expect)(amqpQueue.get).toHaveBeenCalledWith('queue', { noAck: false });
36
- (0, vitest_1.expect)(options.parse).toHaveBeenCalledWith(rawMessage);
37
- (0, vitest_1.expect)(handler.handle).toHaveBeenCalledWith({ ok: true, msg: 'parsed' });
41
+ (0, vitest_1.expect)(handler.handle).toHaveBeenCalledWith({ id: '1' });
38
42
  (0, vitest_1.expect)(amqpQueue.ack).toHaveBeenCalledWith(channel, rawMessage);
39
- (0, vitest_1.expect)(amqpQueue.close).toHaveBeenCalled();
43
+ (0, vitest_1.expect)(amqpQueue.close).toHaveBeenCalledTimes(1);
44
+ (0, vitest_1.expect)(process.exit).toHaveBeenCalledWith(0);
40
45
  });
41
- (0, vitest_1.it)('should not ack if manualAck is false', async () => {
42
- options.manualAck = false;
43
- const rawMessage = { content: Buffer.from('msg') };
44
- const channel = {};
45
- amqpQueue.get.mockResolvedValue({ channel, rawMessage });
46
+ (0, vitest_1.it)('should skip ack when manualAck is disabled', async () => {
47
+ const rawMessage = { content: Buffer.from(JSON.stringify({ id: '1' })) };
48
+ const runner = makeRunner({ manualAck: false });
49
+ amqpQueue.get.mockResolvedValue({ channel: {}, rawMessage });
46
50
  await runner.run();
51
+ (0, vitest_1.expect)(amqpQueue.get).toHaveBeenCalledWith('queue', { noAck: true });
47
52
  (0, vitest_1.expect)(amqpQueue.ack).not.toHaveBeenCalled();
53
+ (0, vitest_1.expect)(amqpQueue.nack).not.toHaveBeenCalled();
48
54
  });
49
- (0, vitest_1.it)('should nack with correct strategy', async () => {
50
- options.errorStrategy = 'nack-requeue';
51
- const rawMessage = { content: Buffer.from('msg') };
55
+ (0, vitest_1.it)('should apply nack-requeue when handler fails', async () => {
56
+ const rawMessage = { content: Buffer.from(JSON.stringify({ id: '1' })) };
52
57
  const channel = {};
58
+ const runner = makeRunner({ errorStrategy: 'nack-requeue' });
53
59
  amqpQueue.get.mockResolvedValue({ channel, rawMessage });
54
- handler.handle = vitest_1.vi.fn(() => {
55
- throw new Error('fail');
56
- });
60
+ handler.handle.mockRejectedValue(new Error('fail'));
57
61
  await runner.run();
58
62
  (0, vitest_1.expect)(amqpQueue.nack).toHaveBeenCalledWith(channel, rawMessage, true);
63
+ (0, vitest_1.expect)(amqpQueue.ack).not.toHaveBeenCalled();
59
64
  });
60
- (0, vitest_1.it)('should nack with default strategy', async () => {
61
- options.errorStrategy = 'nack-dlq';
62
- const rawMessage = { content: Buffer.from('msg') };
63
- const channel = {};
64
- amqpQueue.get.mockResolvedValue({ channel, rawMessage });
65
- handler.handle = vitest_1.vi.fn(() => {
66
- throw new Error('fail');
67
- });
68
- await runner.run();
69
- (0, vitest_1.expect)(amqpQueue.nack).toHaveBeenCalledWith(channel, rawMessage, false);
70
- });
71
- (0, vitest_1.it)('should log and return if no message is available', async () => {
65
+ (0, vitest_1.it)('should stop when there is no message available', async () => {
66
+ const runner = makeRunner();
72
67
  amqpQueue.get.mockResolvedValue(null);
73
68
  await runner.run();
74
69
  (0, vitest_1.expect)(handler.handle).not.toHaveBeenCalled();
70
+ (0, vitest_1.expect)(logger.info).toHaveBeenCalledWith('[RabbitMQScaledJobRunner] Nenhuma mensagem disponível.');
75
71
  });
76
- (0, vitest_1.it)('should log error if amqpQueue.connect throws', async () => {
77
- amqpQueue.connect.mockRejectedValue(new Error('fail'));
78
- await runner.run();
79
- (0, vitest_1.expect)(amqpQueue.connect).toHaveBeenCalledWith('vhost');
80
- });
81
- (0, vitest_1.it)('should log error if amqpQueue.close throws', async () => {
82
- amqpQueue.close.mockRejectedValue(new Error('fail'));
83
- const rawMessage = { content: Buffer.from('msg') };
72
+ (0, vitest_1.it)('should handle timeout and nack the message', async () => {
73
+ vitest_1.vi.useFakeTimers();
74
+ const rawMessage = { content: Buffer.from(JSON.stringify({ id: '1' })) };
84
75
  const channel = {};
76
+ const runner = makeRunner();
85
77
  amqpQueue.get.mockResolvedValue({ channel, rawMessage });
86
- await runner.run();
87
- (0, vitest_1.expect)(amqpQueue.close).toHaveBeenCalled();
78
+ handler.handle.mockImplementation(() => new Promise(() => undefined));
79
+ handler.getTimeoutPerMessageSeconds.mockReturnValue(1);
80
+ const runPromise = runner.run();
81
+ await vitest_1.vi.advanceTimersByTimeAsync(1000);
82
+ await runPromise;
83
+ (0, vitest_1.expect)(amqpQueue.nack).toHaveBeenCalledWith(channel, rawMessage, false);
84
+ (0, vitest_1.expect)(logger.info).toHaveBeenCalledWith('[RabbitMQScaledJobRunner] Erro: Timeout');
88
85
  });
89
- (0, vitest_1.it)('should call onFinally if close fails', async () => {
90
- amqpQueue.close.mockRejectedValue(new Error('fail'));
91
- const rawMessage = { content: Buffer.from('msg') };
92
- const channel = {};
93
- amqpQueue.get.mockResolvedValue({ channel, rawMessage });
94
- await runner.run();
95
- // onFinally is called inside finishProcess
96
- // No assertion needed for logger, just ensure no throw
86
+ (0, vitest_1.it)('should ignore errors when nack strategy fails', async () => {
87
+ const runner = makeRunner({ errorStrategy: 'nack-dlq' });
88
+ amqpQueue.nack.mockRejectedValue(new Error('nack failed'));
89
+ await (0, vitest_1.expect)(runner['errorStrategy']({
90
+ channel: {},
91
+ rawMessage: { content: Buffer.from('{}') },
92
+ })).resolves.toBeUndefined();
93
+ (0, vitest_1.expect)(logger.info).toHaveBeenCalledWith('[RabbitMQScaledJobRunner] Falha ao aplicar estratégia de erro');
97
94
  });
98
- (0, vitest_1.it)('should handle timeout and call nack', async () => {
99
- options.timeoutMs = 10;
100
- handler.handle = vitest_1.vi.fn(() => new Promise(() => { }));
101
- const rawMessage = { content: Buffer.from('msg') };
102
- const channel = {};
103
- amqpQueue.get.mockResolvedValue({ channel, rawMessage });
104
- await runner.run();
105
- (0, vitest_1.expect)(amqpQueue.nack).toHaveBeenCalledWith(channel, rawMessage, false);
95
+ (0, vitest_1.it)('should return early when there is no message to handle as error context', async () => {
96
+ const runner = makeRunner();
97
+ await (0, vitest_1.expect)(runner['handleError'](new Error('fail'), null)).resolves.toBeUndefined();
98
+ (0, vitest_1.expect)(amqpQueue.nack).not.toHaveBeenCalled();
106
99
  });
107
- (0, vitest_1.it)('should handle error in nack gracefully', async () => {
108
- amqpQueue.nack.mockRejectedValue(new Error('fail'));
109
- options.errorStrategy = 'nack-dlq';
110
- const rawMessage = { content: Buffer.from('msg') };
111
- const channel = {};
112
- amqpQueue.get.mockResolvedValue({ channel, rawMessage });
113
- handler.handle = vitest_1.vi.fn(() => {
114
- throw new Error('fail');
115
- });
100
+ (0, vitest_1.it)('should log close errors and still finish the process', async () => {
101
+ const runner = makeRunner();
102
+ amqpQueue.get.mockResolvedValue(null);
103
+ amqpQueue.close.mockRejectedValue(new Error('close failed'));
116
104
  await runner.run();
117
- (0, vitest_1.expect)(amqpQueue.nack).toHaveBeenCalledWith(channel, rawMessage, false);
105
+ (0, vitest_1.expect)(logger.info).toHaveBeenCalledWith('[RabbitMQScaledJobRunner] Erro ao fechar conexão', vitest_1.expect.any(Error));
106
+ (0, vitest_1.expect)(process.exit).toHaveBeenCalledWith(0);
118
107
  });
119
- (0, vitest_1.it)('should handle error in ack gracefully', async () => {
120
- amqpQueue.ack.mockRejectedValue(new Error('fail'));
121
- const rawMessage = { content: Buffer.from('msg') };
122
- const channel = {};
123
- amqpQueue.get.mockResolvedValue({ channel, rawMessage });
108
+ (0, vitest_1.it)('should handle unexpected outer errors and still close', async () => {
109
+ const runner = makeRunner();
110
+ handler.getSimultaneity.mockImplementation(() => {
111
+ throw new Error('outer failure');
112
+ });
124
113
  await runner.run();
125
- (0, vitest_1.expect)(amqpQueue.ack).toHaveBeenCalledWith(channel, rawMessage);
114
+ (0, vitest_1.expect)(logger.info).toHaveBeenCalledWith('[RabbitMQScaledJobRunner] Erro: {}');
115
+ (0, vitest_1.expect)(amqpQueue.close).toHaveBeenCalledTimes(1);
126
116
  });
127
117
  });
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const vitest_1 = require("vitest");
5
+ const { sendMock } = vitest_1.vi.hoisted(() => ({
6
+ sendMock: vitest_1.vi.fn(),
7
+ }));
8
+ vitest_1.vi.mock('@aws-sdk/client-sqs', () => ({
9
+ ReceiveMessageCommand: class ReceiveMessageCommand {
10
+ input;
11
+ constructor(input) {
12
+ this.input = input;
13
+ }
14
+ },
15
+ DeleteMessageCommand: class DeleteMessageCommand {
16
+ input;
17
+ constructor(input) {
18
+ this.input = input;
19
+ }
20
+ },
21
+ SQSClient: class SQSClient {
22
+ config;
23
+ send = sendMock;
24
+ constructor(config) {
25
+ this.config = config;
26
+ }
27
+ },
28
+ }));
29
+ const client_sqs_1 = require("@aws-sdk/client-sqs");
30
+ const handler_1 = tslib_1.__importDefault(require("../../../application/queue/handler"));
31
+ const runner_1 = require("./runner");
32
+ class TestHandler extends handler_1.default {
33
+ handleMock = vitest_1.vi.fn().mockResolvedValue(undefined);
34
+ constructor(simultaneity = 1, timeoutPerMessageSeconds) {
35
+ super();
36
+ this.simultaneity = simultaneity;
37
+ this.timeoutPerMessageSeconds = timeoutPerMessageSeconds;
38
+ }
39
+ async handle(message) {
40
+ await this.handleMock(message);
41
+ }
42
+ }
43
+ const createLogger = () => ({
44
+ info: vitest_1.vi.fn(),
45
+ warn: vitest_1.vi.fn(),
46
+ error: vitest_1.vi.fn(),
47
+ debug: vitest_1.vi.fn(),
48
+ });
49
+ (0, vitest_1.describe)('SQSScaledJobRunner', () => {
50
+ (0, vitest_1.beforeEach)(() => {
51
+ sendMock.mockReset();
52
+ });
53
+ (0, vitest_1.afterEach)(() => {
54
+ vitest_1.vi.useRealTimers();
55
+ vitest_1.vi.restoreAllMocks();
56
+ });
57
+ (0, vitest_1.it)('should receive, process and delete messages from SQS', async () => {
58
+ vitest_1.vi.useFakeTimers();
59
+ const handler = new TestHandler(1, 1);
60
+ const logger = createLogger();
61
+ const runner = new runner_1.SQSScaledJobRunner(handler, 'queue-url', {
62
+ sqsRegion: 'us-east-1',
63
+ waitMessagesTimeSeconds: 5,
64
+ }, logger);
65
+ sendMock
66
+ .mockResolvedValueOnce({
67
+ Messages: [
68
+ {
69
+ Body: JSON.stringify({ id: '1' }),
70
+ ReceiptHandle: 'receipt-handle',
71
+ },
72
+ ],
73
+ })
74
+ .mockResolvedValueOnce({});
75
+ const processPromise = runner.process();
76
+ await vitest_1.vi.runAllTimersAsync();
77
+ await processPromise;
78
+ (0, vitest_1.expect)(sendMock).toHaveBeenNthCalledWith(1, vitest_1.expect.any(client_sqs_1.ReceiveMessageCommand));
79
+ (0, vitest_1.expect)(sendMock.mock.calls[0][0].input).toEqual({
80
+ QueueUrl: 'queue-url',
81
+ MaxNumberOfMessages: 1,
82
+ WaitTimeSeconds: 5,
83
+ });
84
+ (0, vitest_1.expect)(handler.handleMock).toHaveBeenCalledWith({ id: '1' });
85
+ (0, vitest_1.expect)(sendMock).toHaveBeenNthCalledWith(2, vitest_1.expect.any(client_sqs_1.DeleteMessageCommand));
86
+ (0, vitest_1.expect)(sendMock.mock.calls[1][0].input).toEqual({
87
+ QueueUrl: 'queue-url',
88
+ ReceiptHandle: 'receipt-handle',
89
+ });
90
+ (0, vitest_1.expect)(logger.info).toHaveBeenCalledWith('[SQSScaledJobRunner] Mensagem processada com sucesso');
91
+ (0, vitest_1.expect)(logger.info).toHaveBeenCalledWith('[SQSScaledJobRunner] Mensagem deletada');
92
+ });
93
+ (0, vitest_1.it)('should keep polling until simultaneity is reached when there are no messages', async () => {
94
+ const handler = new TestHandler(2);
95
+ const logger = createLogger();
96
+ const runner = new runner_1.SQSScaledJobRunner(handler, 'queue-url', {
97
+ sqsRegion: 'us-east-1',
98
+ }, logger);
99
+ sendMock.mockResolvedValue({
100
+ Messages: [],
101
+ });
102
+ await runner.process();
103
+ (0, vitest_1.expect)(sendMock).toHaveBeenCalledTimes(2);
104
+ (0, vitest_1.expect)(logger.info).toHaveBeenCalledWith('[SQSScaledJobRunner] Nenhuma mensagem disponível.');
105
+ (0, vitest_1.expect)(handler.handleMock).not.toHaveBeenCalled();
106
+ });
107
+ (0, vitest_1.it)('should log invalid messages and guard the parser against unsupported inputs', async () => {
108
+ const handler = new TestHandler();
109
+ const logger = createLogger();
110
+ const runner = new runner_1.SQSScaledJobRunner(handler, 'queue-url', {
111
+ sqsRegion: 'us-east-1',
112
+ }, logger);
113
+ sendMock.mockResolvedValueOnce({
114
+ Messages: [
115
+ {
116
+ Body: null,
117
+ ReceiptHandle: 'receipt-handle',
118
+ },
119
+ ],
120
+ });
121
+ await runner.process();
122
+ (0, vitest_1.expect)(logger.info).toHaveBeenCalledWith(vitest_1.expect.stringContaining('[SQSScaledJobRunner] Erro:'));
123
+ (0, vitest_1.expect)(handler.handleMock).not.toHaveBeenCalled();
124
+ (0, vitest_1.expect)(() => runner_1.SQSScaledJobRunner.parseMessage(undefined)).toThrow('[SQSScaledJobRunner] Mensagem inválida.');
125
+ (0, vitest_1.expect)(() => runner_1.SQSScaledJobRunner.parseMessage(123)).toThrow('[SQSScaledJobRunner] Mensagem deve ser uma string.');
126
+ });
127
+ (0, vitest_1.it)('should race processing with the global timeout when configured', async () => {
128
+ const runner = new runner_1.SQSScaledJobRunner(new TestHandler(), 'queue-url', {
129
+ sqsRegion: 'us-east-1',
130
+ processTimeoutSeconds: 3,
131
+ }, createLogger());
132
+ const processSpy = vitest_1.vi
133
+ .spyOn(runner, 'process')
134
+ .mockImplementation(() => new Promise(() => undefined));
135
+ const timeoutSpy = vitest_1.vi
136
+ .spyOn(runner, 'timeout')
137
+ .mockResolvedValue(undefined);
138
+ await runner.run();
139
+ (0, vitest_1.expect)(processSpy).toHaveBeenCalledTimes(1);
140
+ (0, vitest_1.expect)(timeoutSpy).toHaveBeenCalledWith(3);
141
+ });
142
+ (0, vitest_1.it)('should run processing directly when no global timeout is configured', async () => {
143
+ const runner = new runner_1.SQSScaledJobRunner(new TestHandler(), 'queue-url', {
144
+ sqsRegion: 'us-east-1',
145
+ }, createLogger());
146
+ const processSpy = vitest_1.vi.spyOn(runner, 'process').mockResolvedValue(undefined);
147
+ await runner.run();
148
+ (0, vitest_1.expect)(processSpy).toHaveBeenCalledTimes(1);
149
+ });
150
+ });
@@ -0,0 +1,10 @@
1
+ type TracingResourceAttribute = string | number | boolean | undefined;
2
+ interface IStartTracingOptions {
3
+ serviceName?: string;
4
+ serviceVersion?: string;
5
+ disabledInstrumentations?: string[];
6
+ extraResourceAttributes?: Record<string, TracingResourceAttribute>;
7
+ }
8
+ export declare function shutdownTracing(): Promise<void>;
9
+ export declare function startTracing(options?: IStartTracingOptions): void;
10
+ export {};
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startTracing = exports.shutdownTracing = void 0;
4
+ const auto_instrumentations_node_1 = require("@opentelemetry/auto-instrumentations-node");
5
+ const resources_1 = require("@opentelemetry/resources");
6
+ const sdk_node_1 = require("@opentelemetry/sdk-node");
7
+ const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
8
+ const DEFAULT_DISABLED_INSTRUMENTATIONS = ['@opentelemetry/instrumentation-fs'];
9
+ let sdk = null;
10
+ let isShutdownHookRegistered = false;
11
+ let shutdownPromise = null;
12
+ function makeDisabledInstrumentationMap(disabledInstrumentations) {
13
+ return disabledInstrumentations.reduce((accumulator, instrumentationName) => {
14
+ accumulator[instrumentationName] = { enabled: false };
15
+ return accumulator;
16
+ }, {});
17
+ }
18
+ function shutdownTracing() {
19
+ if (sdk === null) {
20
+ return Promise.resolve();
21
+ }
22
+ if (shutdownPromise !== null) {
23
+ return shutdownPromise;
24
+ }
25
+ const currentShutdownPromise = sdk
26
+ .shutdown()
27
+ .then(() => {
28
+ console.log('Tracing terminated');
29
+ sdk = null;
30
+ })
31
+ .catch((error) => {
32
+ console.log('Error terminating tracing', error);
33
+ throw error;
34
+ })
35
+ .finally(() => {
36
+ shutdownPromise = null;
37
+ });
38
+ shutdownPromise = currentShutdownPromise;
39
+ return currentShutdownPromise;
40
+ }
41
+ exports.shutdownTracing = shutdownTracing;
42
+ function registerShutdownHook() {
43
+ if (isShutdownHookRegistered) {
44
+ return;
45
+ }
46
+ process.on('SIGTERM', () => {
47
+ void shutdownTracing();
48
+ });
49
+ isShutdownHookRegistered = true;
50
+ }
51
+ function startTracing(options = {}) {
52
+ if (sdk !== null) {
53
+ return;
54
+ }
55
+ const serviceName = options.serviceName;
56
+ const serviceVersion = options.serviceVersion;
57
+ const disabledInstrumentations = [
58
+ ...new Set([
59
+ ...DEFAULT_DISABLED_INSTRUMENTATIONS,
60
+ ...(options.disabledInstrumentations ?? []),
61
+ ]),
62
+ ];
63
+ const resourceAttributes = {
64
+ [semantic_conventions_1.ATTR_SERVICE_NAME]: serviceName,
65
+ [semantic_conventions_1.ATTR_SERVICE_VERSION]: serviceVersion,
66
+ ...(options.extraResourceAttributes ?? {}),
67
+ };
68
+ sdk = new sdk_node_1.NodeSDK({
69
+ resource: (0, resources_1.resourceFromAttributes)(resourceAttributes),
70
+ instrumentations: [
71
+ (0, auto_instrumentations_node_1.getNodeAutoInstrumentations)(makeDisabledInstrumentationMap(disabledInstrumentations)),
72
+ ],
73
+ });
74
+ sdk.start();
75
+ console.log('OpenTelemetry tracing started');
76
+ registerShutdownHook();
77
+ }
78
+ exports.startTracing = startTracing;
@@ -433,4 +433,27 @@ describe('Validation zod', () => {
433
433
  }));
434
434
  }
435
435
  });
436
+ test('should return empty sections when the request omits them', async () => {
437
+ const schema = zod_1.z.object({
438
+ body: zod_1.z.object({
439
+ name: zod_1.z.string().optional(),
440
+ }),
441
+ headers: zod_1.z.object({
442
+ tenantid: zod_1.z.string().optional(),
443
+ }),
444
+ query: zod_1.z.object({
445
+ page: zod_1.z.string().optional(),
446
+ }),
447
+ params: zod_1.z.object({
448
+ id: zod_1.z.string().optional(),
449
+ }),
450
+ });
451
+ const validation = new validation_zod_1.default(schema);
452
+ await expect(validation.validate({})).resolves.toEqual({
453
+ body: {},
454
+ headers: {},
455
+ params: {},
456
+ query: {},
457
+ });
458
+ });
436
459
  });
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const get_take_and_skip_1 = require("./get-take-and-skip");
5
+ (0, vitest_1.describe)('getTakeAndSkip', () => {
6
+ (0, vitest_1.it)('should parse pagination values and apply defaults', () => {
7
+ (0, vitest_1.expect)((0, get_take_and_skip_1.getTakeAndSkip)('10', '2')).toEqual({
8
+ take: 10,
9
+ skip: 2,
10
+ });
11
+ (0, vitest_1.expect)((0, get_take_and_skip_1.getTakeAndSkip)('', '')).toEqual({
12
+ take: 20,
13
+ skip: 1,
14
+ });
15
+ });
16
+ });
@@ -0,0 +1 @@
1
+ declare function jumpToCode(event: any): void;
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+ /* eslint-disable */
3
+ var jumpToCode = (function init() {
4
+ // Classes of code we would like to highlight in the file view
5
+ var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
6
+ // Elements to highlight in the file listing view
7
+ var fileListingElements = ['td.pct.low'];
8
+ // We don't want to select elements that are direct descendants of another match
9
+ var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
10
+ // Selecter that finds elements on the page to which we can jump
11
+ var selector =
12
+ fileListingElements.join(', ') +
13
+ ', ' +
14
+ notSelector +
15
+ missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
16
+ // The NodeList of matching elements
17
+ var missingCoverageElements = document.querySelectorAll(selector);
18
+ var currentIndex;
19
+ function toggleClass(index) {
20
+ missingCoverageElements.item(currentIndex).classList.remove('highlighted');
21
+ missingCoverageElements.item(index).classList.add('highlighted');
22
+ }
23
+ function makeCurrent(index) {
24
+ toggleClass(index);
25
+ currentIndex = index;
26
+ missingCoverageElements.item(index).scrollIntoView({
27
+ behavior: 'smooth',
28
+ block: 'center',
29
+ inline: 'center',
30
+ });
31
+ }
32
+ function goToPrevious() {
33
+ var nextIndex = 0;
34
+ if (typeof currentIndex !== 'number' || currentIndex === 0) {
35
+ nextIndex = missingCoverageElements.length - 1;
36
+ } else if (missingCoverageElements.length > 1) {
37
+ nextIndex = currentIndex - 1;
38
+ }
39
+ makeCurrent(nextIndex);
40
+ }
41
+ function goToNext() {
42
+ var nextIndex = 0;
43
+ if (
44
+ typeof currentIndex === 'number' &&
45
+ currentIndex < missingCoverageElements.length - 1
46
+ ) {
47
+ nextIndex = currentIndex + 1;
48
+ }
49
+ makeCurrent(nextIndex);
50
+ }
51
+ return function jump(event) {
52
+ if (
53
+ document.getElementById('fileSearch') === document.activeElement &&
54
+ document.activeElement != null
55
+ ) {
56
+ // if we're currently focused on the search input, we don't want to navigate
57
+ return;
58
+ }
59
+ switch (event.which) {
60
+ case 78: // n
61
+ case 74: // j
62
+ goToNext();
63
+ break;
64
+ case 66: // b
65
+ case 75: // k
66
+ case 80: // p
67
+ goToPrevious();
68
+ break;
69
+ }
70
+ };
71
+ })();
72
+ window.addEventListener('keydown', jumpToCode);
File without changes