@devrev/ts-adaas 1.6.0 → 1.7.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.
@@ -60,6 +60,5 @@ async function installInitialDomainMapping(event, initialDomainMappingJson) {
60
60
  Authorization: devrevToken,
61
61
  },
62
62
  });
63
- console.log('Successfully installed initial domain mapping: ' +
64
- JSON.stringify(initialDomainMappingInstallResponse.data));
63
+ console.log(`Successfully installed initial domain mapping ${JSON.stringify(initialDomainMappingInstallResponse.data)}`);
65
64
  }
@@ -46,7 +46,9 @@ describe('installInitialDomainMapping', () => {
46
46
  // Re-initialize the spy and its mock implementation
47
47
  mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => { });
48
48
  mockConsoleWarn = jest.spyOn(console, 'warn').mockImplementation(() => { });
49
- mockConsoleError = jest.spyOn(console, 'error').mockImplementation(() => { });
49
+ mockConsoleError = jest
50
+ .spyOn(console, 'error')
51
+ .mockImplementation(() => { });
50
52
  });
51
53
  // After each test, clear all mocks to prevent state from leaking.
52
54
  afterEach(() => {
@@ -104,7 +106,7 @@ describe('installInitialDomainMapping', () => {
104
106
  },
105
107
  });
106
108
  expect(mockConsoleLog).toHaveBeenCalledWith('Successfully created recipe blueprint with id: recipe-blueprint-123');
107
- expect(mockConsoleLog).toHaveBeenCalledWith('Successfully installed initial domain mapping: {"success":true,"mapping_id":"mapping-123"}');
109
+ expect(mockConsoleLog).toHaveBeenCalledWith(`Successfully installed initial domain mapping ${JSON.stringify(mockDomainMappingResponse.data)}`);
108
110
  });
109
111
  it('should successfully install without recipe blueprint when not provided', async () => {
110
112
  const mappingWithoutBlueprint = {
@@ -3,7 +3,9 @@ import { LoggerFactoryInterface, LogLevel, PrintableState } from './logger.inter
3
3
  import { AxiosError, RawAxiosResponseHeaders } from 'axios';
4
4
  export declare class Logger extends Console {
5
5
  private options?;
6
+ private tags;
6
7
  constructor({ event, options }: LoggerFactoryInterface);
8
+ private valueToString;
7
9
  logFn(args: unknown[], level: LogLevel): void;
8
10
  log(...args: unknown[]): void;
9
11
  info(...args: unknown[]): void;
@@ -1,26 +1,29 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.serializeError = exports.Logger = void 0;
7
4
  exports.getPrintableState = getPrintableState;
8
5
  exports.formatAxiosError = formatAxiosError;
9
6
  exports.serializeAxiosError = serializeAxiosError;
10
- const lambda_log_1 = __importDefault(require("lambda-log"));
11
7
  const node_console_1 = require("node:console");
8
+ const node_util_1 = require("node:util");
12
9
  const logger_interfaces_1 = require("./logger.interfaces");
13
10
  const node_worker_threads_1 = require("node:worker_threads");
14
11
  const workers_1 = require("../types/workers");
15
- const helpers_1 = require("../common/helpers");
16
12
  class Logger extends node_console_1.Console {
17
13
  constructor({ event, options }) {
18
14
  super(process.stdout, process.stderr);
19
15
  this.options = options;
20
- lambda_log_1.default.options.levelKey = null;
21
- lambda_log_1.default.options.tagsKey = null;
22
- lambda_log_1.default.options.messageKey = 'message';
23
- lambda_log_1.default.options.meta = Object.assign(Object.assign({}, event.payload.event_context), { dev_oid: event.payload.event_context.dev_org });
16
+ this.tags = Object.assign(Object.assign({}, event.payload.event_context), { dev_oid: event.payload.event_context.dev_org });
17
+ }
18
+ valueToString(value) {
19
+ if (typeof value === 'string') {
20
+ return value;
21
+ }
22
+ // Use Node.js built-in inspect for everything including errors
23
+ return (0, node_util_1.inspect)(value, {
24
+ compact: false,
25
+ breakLength: Infinity,
26
+ });
24
27
  }
25
28
  logFn(args, level) {
26
29
  var _a;
@@ -29,14 +32,28 @@ class Logger extends node_console_1.Console {
29
32
  console[level](...args);
30
33
  }
31
34
  else {
32
- lambda_log_1.default.log(level, JSON.stringify(args));
35
+ let message;
36
+ if (args.length === 1 && typeof args[0] === 'string') {
37
+ // Single string argument - use directly
38
+ message = args[0];
39
+ }
40
+ else if (args.length === 1) {
41
+ // Single non-string argument - convert to string properly
42
+ message = this.valueToString(args[0]);
43
+ }
44
+ else {
45
+ // Multiple arguments - create a readable format
46
+ message = args.map((arg) => this.valueToString(arg)).join(' ');
47
+ }
48
+ const logObject = Object.assign({ message }, this.tags);
49
+ console[level](JSON.stringify(logObject));
33
50
  }
34
51
  }
35
52
  else {
36
53
  node_worker_threads_1.parentPort === null || node_worker_threads_1.parentPort === void 0 ? void 0 : node_worker_threads_1.parentPort.postMessage({
37
54
  subject: workers_1.WorkerMessageSubject.WorkerMessageLog,
38
55
  payload: {
39
- args: JSON.parse(JSON.stringify(args, (0, helpers_1.getCircularReplacer)())),
56
+ args: args.map((arg) => this.valueToString(arg)),
40
57
  level,
41
58
  },
42
59
  });
@@ -1,6 +1,184 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const node_util_1 = require("node:util");
3
4
  const logger_1 = require("./logger");
5
+ const extraction_1 = require("../types/extraction");
6
+ const test_helpers_1 = require("../tests/test-helpers");
7
+ // Mock console methods
8
+ const mockConsoleInfo = jest.spyOn(console, 'info').mockImplementation();
9
+ const mockConsoleWarn = jest.spyOn(console, 'warn').mockImplementation();
10
+ const mockConsoleError = jest.spyOn(console, 'error').mockImplementation();
11
+ const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation();
12
+ // Mock worker_threads
13
+ jest.mock('node:worker_threads', () => ({
14
+ isMainThread: true,
15
+ parentPort: null,
16
+ }));
17
+ describe('Logger', () => {
18
+ let mockEvent;
19
+ let mockOptions;
20
+ beforeEach(() => {
21
+ jest.clearAllMocks();
22
+ mockEvent = (0, test_helpers_1.createEvent)({
23
+ eventType: extraction_1.EventType.ExtractionDataStart,
24
+ eventContextOverrides: {
25
+ dev_org: 'DEV-test',
26
+ dev_org_id: 'DEV-test-id',
27
+ dev_user: 'DEVU-test',
28
+ dev_user_id: 'DEVU-test-id',
29
+ external_sync_unit: 'test-unit',
30
+ external_sync_unit_id: 'test-unit-id',
31
+ external_sync_unit_name: 'test-unit-name',
32
+ external_system: 'test-system',
33
+ external_system_type: 'test-type',
34
+ import_slug: 'test-import',
35
+ request_id: 'test-request-id',
36
+ snap_in_slug: 'test-snap-slug',
37
+ sync_run: 'test-sync-run',
38
+ sync_run_id: 'test-sync-run-id',
39
+ },
40
+ });
41
+ mockOptions = {
42
+ isLocalDevelopment: false,
43
+ };
44
+ });
45
+ afterAll(() => {
46
+ jest.restoreAllMocks();
47
+ });
48
+ describe('constructor', () => {
49
+ it('should initialize logger with event context and dev_oid', () => {
50
+ const logger = new logger_1.Logger({ event: mockEvent, options: mockOptions });
51
+ // Access private property for testing
52
+ const tags = logger.tags;
53
+ expect(tags).toEqual(Object.assign(Object.assign({}, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.dev_org }));
54
+ });
55
+ });
56
+ describe('production logging', () => {
57
+ let logger;
58
+ beforeEach(() => {
59
+ mockOptions.isLocalDevelopment = false;
60
+ logger = new logger_1.Logger({ event: mockEvent, options: mockOptions });
61
+ });
62
+ it('should log single string message without backslashes', () => {
63
+ const message = 'Worker is online. Started processing the task.';
64
+ logger.info(message);
65
+ expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.dev_org })));
66
+ });
67
+ it('should log single object message with JSON stringify', () => {
68
+ const data = { id: 123, name: 'test' };
69
+ logger.info(data);
70
+ const expectedMessage = (0, node_util_1.inspect)(data, {
71
+ compact: false,
72
+ breakLength: Infinity,
73
+ });
74
+ expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message: expectedMessage }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.dev_org })));
75
+ });
76
+ it('should log multiple arguments joined with space', () => {
77
+ const text = 'Successfully fetched';
78
+ const data = { count: 42 };
79
+ logger.info(text, data);
80
+ const expectedDataMessage = (0, node_util_1.inspect)(data, {
81
+ compact: false,
82
+ breakLength: Infinity,
83
+ });
84
+ expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message: `${text} ${expectedDataMessage}` }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.dev_org })));
85
+ });
86
+ it('should handle mixed string and object arguments', () => {
87
+ const text1 = 'Processing';
88
+ const data = { id: 123 };
89
+ const text2 = 'completed';
90
+ logger.info(text1, data, text2);
91
+ const expectedDataMessage = (0, node_util_1.inspect)(data, {
92
+ compact: false,
93
+ breakLength: Infinity,
94
+ });
95
+ expect(mockConsoleInfo).toHaveBeenCalledWith(JSON.stringify(Object.assign(Object.assign({ message: `${text1} ${expectedDataMessage} ${text2}` }, mockEvent.payload.event_context), { dev_oid: mockEvent.payload.event_context.dev_org })));
96
+ });
97
+ });
98
+ describe('local development logging', () => {
99
+ let logger;
100
+ beforeEach(() => {
101
+ mockOptions.isLocalDevelopment = true;
102
+ logger = new logger_1.Logger({ event: mockEvent, options: mockOptions });
103
+ });
104
+ it('should use regular console methods in local development', () => {
105
+ const message = 'Test message';
106
+ const data = { test: true };
107
+ logger.info(message, data);
108
+ expect(mockConsoleInfo).toHaveBeenCalledWith(message, data);
109
+ });
110
+ });
111
+ describe('log levels', () => {
112
+ let logger;
113
+ beforeEach(() => {
114
+ mockOptions.isLocalDevelopment = false;
115
+ logger = new logger_1.Logger({ event: mockEvent, options: mockOptions });
116
+ });
117
+ it('should call console.info for info level', () => {
118
+ logger.info('test message');
119
+ expect(mockConsoleInfo).toHaveBeenCalled();
120
+ });
121
+ it('should call console.warn for warn level', () => {
122
+ logger.warn('test warning');
123
+ expect(mockConsoleWarn).toHaveBeenCalled();
124
+ });
125
+ it('should call console.error for error level', () => {
126
+ logger.error('test error');
127
+ expect(mockConsoleError).toHaveBeenCalled();
128
+ });
129
+ it('should call console.info for log level', () => {
130
+ logger.log('test log');
131
+ expect(mockConsoleInfo).toHaveBeenCalled();
132
+ });
133
+ });
134
+ describe('edge cases', () => {
135
+ let logger;
136
+ beforeEach(() => {
137
+ mockOptions.isLocalDevelopment = false;
138
+ logger = new logger_1.Logger({ event: mockEvent, options: mockOptions });
139
+ });
140
+ it('should handle empty string message', () => {
141
+ logger.info('');
142
+ expect(mockConsoleInfo).toHaveBeenCalledTimes(1);
143
+ const callArgs = mockConsoleInfo.mock.calls[0][0];
144
+ const logObject = JSON.parse(callArgs);
145
+ expect(logObject.message).toBe('');
146
+ expect(logObject.dev_oid).toBe(mockEvent.payload.event_context.dev_org);
147
+ expect(logObject.request_id).toBe(mockEvent.payload.event_context.request_id);
148
+ });
149
+ it('should handle null and undefined values', () => {
150
+ logger.info('test', null, undefined);
151
+ expect(mockConsoleInfo).toHaveBeenCalledTimes(1);
152
+ const callArgs = mockConsoleInfo.mock.calls[0][0];
153
+ const logObject = JSON.parse(callArgs);
154
+ // inspect shows 'null' and 'undefined' as strings
155
+ expect(logObject.message).toBe('test null undefined');
156
+ expect(logObject.dev_oid).toBe(mockEvent.payload.event_context.dev_org);
157
+ });
158
+ it('should handle complex nested objects', () => {
159
+ const complexObject = {
160
+ level1: {
161
+ level2: {
162
+ array: [1, 2, 3],
163
+ string: 'nested',
164
+ },
165
+ },
166
+ };
167
+ logger.info(complexObject);
168
+ expect(mockConsoleInfo).toHaveBeenCalledTimes(1);
169
+ const callArgs = mockConsoleInfo.mock.calls[0][0];
170
+ const logObject = JSON.parse(callArgs);
171
+ // The logger uses inspect() with formatting, not JSON.stringify()
172
+ const expectedMessage = require('util').inspect(complexObject, {
173
+ compact: false,
174
+ breakLength: Infinity,
175
+ });
176
+ expect(logObject.message).toBe(expectedMessage);
177
+ expect(logObject.dev_oid).toBe(mockEvent.payload.event_context.dev_org);
178
+ expect(typeof logObject.callback_url).toBe('string');
179
+ });
180
+ });
181
+ });
4
182
  it('getPrintableState should return printable state', () => {
5
183
  const state = {
6
184
  test_key: 'test_value',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devrev/ts-adaas",
3
- "version": "1.6.0",
3
+ "version": "1.7.0-beta.0",
4
4
  "description": "Typescript library containing the ADaaS(AirDrop as a Service) control protocol.",
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",
@@ -34,8 +34,7 @@
34
34
  "eslint-config-prettier": "^10.1.5",
35
35
  "eslint-plugin-prettier": "^5.1.3",
36
36
  "jest": "^29.7.0",
37
- "ts-jest": "^29.3.3",
38
- "typescript": "^5.3.3"
37
+ "ts-jest": "^29.3.3"
39
38
  },
40
39
  "dependencies": {
41
40
  "@devrev/typescript-sdk": "^1.1.59",
@@ -43,8 +42,8 @@
43
42
  "axios-retry": "^4.5.0",
44
43
  "form-data": "^4.0.1",
45
44
  "js-jsonl": "^1.1.1",
46
- "lambda-log": "^3.1.0",
47
45
  "ts-node": "^10.9.2",
46
+ "typescript": "^5.3.3",
48
47
  "yargs": "^17.7.2"
49
48
  },
50
49
  "files": [