@devrev/ts-adaas 1.5.1 → 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.
Files changed (47) hide show
  1. package/dist/common/constants.d.ts +5 -1
  2. package/dist/common/constants.js +6 -2
  3. package/dist/common/control-protocol.js +1 -1
  4. package/dist/common/helpers.d.ts +2 -1
  5. package/dist/common/helpers.js +15 -0
  6. package/dist/{tests/from_devrev/loading.test.js → common/helpers.test.js} +1 -1
  7. package/dist/common/install-initial-domain-mapping.js +36 -56
  8. package/dist/common/install-initial-domain-mapping.test.js +217 -0
  9. package/dist/logger/logger.d.ts +2 -0
  10. package/dist/logger/logger.js +28 -11
  11. package/dist/logger/logger.test.js +178 -0
  12. package/dist/repo/repo.interfaces.d.ts +1 -0
  13. package/dist/state/state.js +21 -12
  14. package/dist/tests/mock-server.d.ts +20 -0
  15. package/dist/tests/mock-server.js +278 -0
  16. package/dist/tests/test-helpers.d.ts +1 -1
  17. package/dist/tests/test-helpers.interfaces.d.ts +3 -1
  18. package/dist/tests/test-helpers.js +27 -28
  19. package/dist/tests/timeout-handling/extraction.d.ts +3 -0
  20. package/dist/tests/timeout-handling/extraction.js +21 -0
  21. package/dist/tests/timeout-handling/timeout-1.d.ts +1 -0
  22. package/dist/tests/timeout-handling/timeout-1.js +14 -0
  23. package/dist/tests/timeout-handling/timeout-1.test.d.ts +1 -0
  24. package/dist/tests/timeout-handling/timeout-1.test.js +45 -0
  25. package/dist/tests/timeout-handling/timeout-2.d.ts +1 -0
  26. package/dist/tests/timeout-handling/timeout-2.js +42 -0
  27. package/dist/tests/timeout-handling/timeout-2.test.d.ts +1 -0
  28. package/dist/tests/timeout-handling/timeout-2.test.js +46 -0
  29. package/dist/tests/timeout-handling/timeout-3a.d.ts +1 -0
  30. package/dist/tests/timeout-handling/timeout-3a.js +37 -0
  31. package/dist/tests/timeout-handling/timeout-3a.test.d.ts +1 -0
  32. package/dist/tests/timeout-handling/timeout-3a.test.js +46 -0
  33. package/dist/tests/timeout-handling/timeout-3b.d.ts +1 -0
  34. package/dist/tests/timeout-handling/timeout-3b.js +38 -0
  35. package/dist/tests/timeout-handling/timeout-3b.test.d.ts +1 -0
  36. package/dist/tests/timeout-handling/timeout-3b.test.js +46 -0
  37. package/dist/types/workers.d.ts +1 -8
  38. package/dist/types/workers.js +0 -1
  39. package/dist/uploader/uploader.js +2 -1
  40. package/dist/uploader/uploader.test.js +3 -0
  41. package/dist/workers/process-task.js +0 -4
  42. package/dist/workers/spawn.d.ts +3 -1
  43. package/dist/workers/spawn.js +47 -39
  44. package/package.json +5 -5
  45. package/dist/tests/test-worker.js +0 -14
  46. /package/dist/{tests/from_devrev/loading.test.d.ts → common/helpers.test.d.ts} +0 -0
  47. /package/dist/{tests/test-worker.d.ts → common/install-initial-domain-mapping.test.d.ts} +0 -0
@@ -5,10 +5,14 @@ export declare const ALLOWED_LOADING_EVENT_TYPES: EventType[];
5
5
  export declare const ALLOWED_EVENT_TYPES: EventType[];
6
6
  export declare const ARTIFACT_BATCH_SIZE = 2000;
7
7
  export declare const MAX_DEVREV_ARTIFACT_SIZE = 262144000;
8
+ export declare const MAX_DEVREV_FILENAME_LENGTH = 256;
9
+ export declare const MAX_DEVREV_FILENAME_EXTENSION_LENGTH = 20;
8
10
  export declare const AIRDROP_DEFAULT_ITEM_TYPES: {
9
11
  EXTERNAL_DOMAIN_METADATA: string;
10
12
  ATTACHMENTS: string;
11
13
  SSOR_ATTACHMENT: string;
12
14
  };
13
15
  export declare const LIBRARY_VERSION: any;
14
- export declare const DEFAULT_SLEEP_DELAY_MS = 180000;
16
+ export declare const DEFAULT_LAMBDA_TIMEOUT: number;
17
+ export declare const HARD_TIMEOUT_MULTIPLIER = 1.3;
18
+ export declare const DEFAULT_SLEEP_DELAY_MS: number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_SLEEP_DELAY_MS = exports.LIBRARY_VERSION = exports.AIRDROP_DEFAULT_ITEM_TYPES = exports.MAX_DEVREV_ARTIFACT_SIZE = exports.ARTIFACT_BATCH_SIZE = exports.ALLOWED_EVENT_TYPES = exports.ALLOWED_LOADING_EVENT_TYPES = exports.ALLOWED_EXTRACTION_EVENT_TYPES = exports.STATELESS_EVENT_TYPES = void 0;
3
+ exports.DEFAULT_SLEEP_DELAY_MS = exports.HARD_TIMEOUT_MULTIPLIER = exports.DEFAULT_LAMBDA_TIMEOUT = exports.LIBRARY_VERSION = exports.AIRDROP_DEFAULT_ITEM_TYPES = exports.MAX_DEVREV_FILENAME_EXTENSION_LENGTH = exports.MAX_DEVREV_FILENAME_LENGTH = exports.MAX_DEVREV_ARTIFACT_SIZE = exports.ARTIFACT_BATCH_SIZE = exports.ALLOWED_EVENT_TYPES = exports.ALLOWED_LOADING_EVENT_TYPES = exports.ALLOWED_EXTRACTION_EVENT_TYPES = exports.STATELESS_EVENT_TYPES = void 0;
4
4
  const extraction_1 = require("../types/extraction");
5
5
  const helpers_1 = require("./helpers");
6
6
  exports.STATELESS_EVENT_TYPES = [
@@ -33,10 +33,14 @@ exports.ALLOWED_EVENT_TYPES = [
33
33
  ];
34
34
  exports.ARTIFACT_BATCH_SIZE = 2000;
35
35
  exports.MAX_DEVREV_ARTIFACT_SIZE = 262144000; // 250MB
36
+ exports.MAX_DEVREV_FILENAME_LENGTH = 256;
37
+ exports.MAX_DEVREV_FILENAME_EXTENSION_LENGTH = 20; // 20 characters for the file extension
36
38
  exports.AIRDROP_DEFAULT_ITEM_TYPES = {
37
39
  EXTERNAL_DOMAIN_METADATA: 'external_domain_metadata',
38
40
  ATTACHMENTS: 'attachments',
39
41
  SSOR_ATTACHMENT: 'ssor_attachment',
40
42
  };
41
43
  exports.LIBRARY_VERSION = (0, helpers_1.getLibraryVersion)();
42
- exports.DEFAULT_SLEEP_DELAY_MS = 180000; // 3 minutes
44
+ exports.DEFAULT_LAMBDA_TIMEOUT = 10 * 60 * 1000; // 10 minutes
45
+ exports.HARD_TIMEOUT_MULTIPLIER = 1.3;
46
+ exports.DEFAULT_SLEEP_DELAY_MS = 3 * 60 * 1000; // 3 minutes
@@ -12,7 +12,7 @@ const emit = async ({ event, eventType, data, }) => {
12
12
  adaas_library_version: constants_1.LIBRARY_VERSION,
13
13
  },
14
14
  };
15
- console.info('Emitting event', JSON.stringify(newEvent));
15
+ console.info('Emitting event', newEvent);
16
16
  return axios_client_1.axiosClient.post(event.payload.event_context.callback_url, Object.assign({}, newEvent), {
17
17
  headers: {
18
18
  Accept: 'application/json, text/plain, */*',
@@ -2,7 +2,7 @@ import { AirdropEvent, EventType, ExtractorEventType } from '../types/extraction
2
2
  import { FileToLoad, LoaderEventType, LoaderReport, StatsFileObject } from '../types/loading';
3
3
  export declare function getTimeoutErrorEventType(eventType: EventType): {
4
4
  eventType: ExtractorEventType | LoaderEventType;
5
- } | null;
5
+ };
6
6
  export declare function getSyncDirection({ event }: {
7
7
  event: AirdropEvent;
8
8
  }): string;
@@ -17,3 +17,4 @@ export declare function addReportToLoaderReport({ loaderReports, report, }: {
17
17
  export declare function getCircularReplacer(): (key: any, value: any) => any;
18
18
  export declare function getLibraryVersion(): any;
19
19
  export declare function sleep(ms: number): Promise<unknown>;
20
+ export declare function truncateFilename(filename: string): string;
@@ -40,10 +40,12 @@ exports.addReportToLoaderReport = addReportToLoaderReport;
40
40
  exports.getCircularReplacer = getCircularReplacer;
41
41
  exports.getLibraryVersion = getLibraryVersion;
42
42
  exports.sleep = sleep;
43
+ exports.truncateFilename = truncateFilename;
43
44
  const extraction_1 = require("../types/extraction");
44
45
  const loading_1 = require("../types/loading");
45
46
  const fs_1 = require("fs");
46
47
  const path = __importStar(require("path"));
48
+ const constants_1 = require("./constants");
47
49
  function getTimeoutErrorEventType(eventType) {
48
50
  switch (eventType) {
49
51
  case extraction_1.EventType.ExtractionMetadataStart:
@@ -181,3 +183,16 @@ function sleep(ms) {
181
183
  console.log(`Sleeping for ${ms}ms.`);
182
184
  return new Promise((resolve) => setTimeout(resolve, ms));
183
185
  }
186
+ function truncateFilename(filename) {
187
+ // If the filename is already within the limit, return it as is.
188
+ if (filename.length <= constants_1.MAX_DEVREV_FILENAME_LENGTH) {
189
+ return filename;
190
+ }
191
+ console.warn(`Filename length exceeds the maximum limit of ${constants_1.MAX_DEVREV_FILENAME_LENGTH} characters. Truncating filename.`);
192
+ let extension = filename.slice(-constants_1.MAX_DEVREV_FILENAME_EXTENSION_LENGTH);
193
+ // Calculate how many characters are available for the name part after accounting for the extension and "..."
194
+ const availableNameLength = constants_1.MAX_DEVREV_FILENAME_LENGTH - constants_1.MAX_DEVREV_FILENAME_EXTENSION_LENGTH - 3; // -3 for "..."
195
+ // Truncate the name part and add an ellipsis
196
+ const truncatedFilename = filename.slice(0, availableNameLength);
197
+ return `${truncatedFilename}...${extension}`;
198
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const helpers_1 = require("../../common/helpers");
3
+ const helpers_1 = require("./helpers");
4
4
  describe('getFilesToLoad', () => {
5
5
  let statsFile;
6
6
  beforeEach(() => {
@@ -12,73 +12,53 @@ async function installInitialDomainMapping(event, initialDomainMappingJson) {
12
12
  console.warn('No initial domain mapping found.');
13
13
  return;
14
14
  }
15
- try {
16
- const snapInResponse = await axios_client_1.axiosClient.get(devrevEndpoint + '/internal/snap-ins.get', {
17
- headers: {
18
- Authorization: devrevToken,
19
- },
20
- params: {
21
- id: snapInId,
22
- },
23
- });
24
- const importSlug = (_d = (_c = (_b = (_a = snapInResponse.data) === null || _a === void 0 ? void 0 : _a.snap_in) === null || _b === void 0 ? void 0 : _b.imports) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.name;
25
- const snapInSlug = (_g = (_f = (_e = snapInResponse.data) === null || _e === void 0 ? void 0 : _e.snap_in) === null || _f === void 0 ? void 0 : _f.snap_in_version) === null || _g === void 0 ? void 0 : _g.slug;
26
- if (!importSlug || !snapInSlug) {
27
- console.error('No import slug and snap in slug found in . Snap in response:', snapInResponse.data);
28
- return;
29
- }
30
- const startingRecipeBlueprint = initialDomainMappingJson === null || initialDomainMappingJson === void 0 ? void 0 : initialDomainMappingJson.starting_recipe_blueprint;
31
- let recipeBlueprintId;
32
- if (startingRecipeBlueprint &&
33
- Object.keys(startingRecipeBlueprint).length !== 0) {
34
- try {
35
- const recipeBlueprintResponse = await axios_client_1.axiosClient.post(`${devrevEndpoint}/internal/airdrop.recipe.blueprints.create`, Object.assign({}, startingRecipeBlueprint), {
36
- headers: {
37
- Authorization: devrevToken,
38
- },
39
- });
40
- recipeBlueprintId = recipeBlueprintResponse.data.recipe_blueprint.id;
41
- console.log('Successfully created recipe blueprint with id: ' + recipeBlueprintId);
42
- }
43
- catch (error) {
44
- if (axios_client_1.axios.isAxiosError(error)) {
45
- console.error('Error while creating recipe blueprint', (0, logger_1.serializeAxiosError)(error));
46
- }
47
- else {
48
- console.error('Error while creating recipe blueprint', error);
49
- }
50
- }
51
- }
15
+ // Get snap-in details
16
+ const snapInResponse = await axios_client_1.axiosClient.get(devrevEndpoint + '/internal/snap-ins.get', {
17
+ headers: {
18
+ Authorization: devrevToken,
19
+ },
20
+ params: {
21
+ id: snapInId,
22
+ },
23
+ });
24
+ const importSlug = (_d = (_c = (_b = (_a = snapInResponse.data) === null || _a === void 0 ? void 0 : _a.snap_in) === null || _b === void 0 ? void 0 : _b.imports) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.name;
25
+ const snapInSlug = (_g = (_f = (_e = snapInResponse.data) === null || _e === void 0 ? void 0 : _e.snap_in) === null || _f === void 0 ? void 0 : _f.snap_in_version) === null || _g === void 0 ? void 0 : _g.slug;
26
+ if (!importSlug || !snapInSlug) {
27
+ const errorMessage = `No import slug or snap-in slug found. Snap-in response: ${snapInResponse.data}`;
28
+ throw new Error(errorMessage);
29
+ }
30
+ const startingRecipeBlueprint = initialDomainMappingJson === null || initialDomainMappingJson === void 0 ? void 0 : initialDomainMappingJson.starting_recipe_blueprint;
31
+ // Try to create a recipe blueprint
32
+ let recipeBlueprintId;
33
+ if (startingRecipeBlueprint &&
34
+ Object.keys(startingRecipeBlueprint).length !== 0) {
52
35
  try {
53
- // 2. Install the initial domain mappings
54
- const additionalMappings = initialDomainMappingJson.additional_mappings || {};
55
- const initialDomainMappingInstallResponse = await axios_client_1.axiosClient.post(`${devrevEndpoint}/internal/airdrop.recipe.initial-domain-mappings.install`, Object.assign(Object.assign({ external_system_type: 'ADaaS', import_slug: importSlug, snap_in_slug: snapInSlug }, (recipeBlueprintId && {
56
- starting_recipe_blueprint: recipeBlueprintId,
57
- })), additionalMappings), {
36
+ const recipeBlueprintResponse = await axios_client_1.axiosClient.post(`${devrevEndpoint}/internal/airdrop.recipe.blueprints.create`, Object.assign({}, startingRecipeBlueprint), {
58
37
  headers: {
59
38
  Authorization: devrevToken,
60
39
  },
61
40
  });
62
- console.log('Successfully installed initial domain mapping: ' +
63
- JSON.stringify(initialDomainMappingInstallResponse.data));
41
+ recipeBlueprintId = recipeBlueprintResponse.data.recipe_blueprint.id;
42
+ console.log('Successfully created recipe blueprint with id: ' + recipeBlueprintId);
64
43
  }
65
44
  catch (error) {
45
+ const errorMessage = `Error while creating recipe blueprint. Continuing without it.`;
66
46
  if (axios_client_1.axios.isAxiosError(error)) {
67
- console.error('Error while installing initial domain mapping', (0, logger_1.serializeAxiosError)(error));
47
+ console.error(errorMessage, (0, logger_1.serializeAxiosError)(error));
68
48
  }
69
49
  else {
70
- console.error('Error while installing initial domain mapping', error);
50
+ console.error(errorMessage, error);
71
51
  }
72
- return;
73
52
  }
74
53
  }
75
- catch (error) {
76
- if (axios_client_1.axios.isAxiosError(error)) {
77
- console.error('Error while fetching snap in', (0, logger_1.serializeAxiosError)(error));
78
- }
79
- else {
80
- console.error('Error while fetching snap in', error);
81
- }
82
- return;
83
- }
54
+ // Install the initial domain mappings
55
+ const additionalMappings = initialDomainMappingJson.additional_mappings || {};
56
+ const initialDomainMappingInstallResponse = await axios_client_1.axiosClient.post(`${devrevEndpoint}/internal/airdrop.recipe.initial-domain-mappings.install`, Object.assign(Object.assign({ external_system_type: 'ADaaS', import_slug: importSlug, snap_in_slug: snapInSlug }, (recipeBlueprintId && {
57
+ starting_recipe_blueprint: recipeBlueprintId,
58
+ })), additionalMappings), {
59
+ headers: {
60
+ Authorization: devrevToken,
61
+ },
62
+ });
63
+ console.log(`Successfully installed initial domain mapping ${JSON.stringify(initialDomainMappingInstallResponse.data)}`);
84
64
  }
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const axios_1 = __importDefault(require("axios"));
7
+ const install_initial_domain_mapping_1 = require("./install-initial-domain-mapping");
8
+ const axios_client_1 = require("../http/axios-client");
9
+ const logger_1 = require("../logger/logger");
10
+ const test_helpers_1 = require("../tests/test-helpers");
11
+ const extraction_1 = require("../types/extraction");
12
+ // Mock dependencies
13
+ jest.mock('axios', () => (Object.assign(Object.assign({}, jest.requireActual('axios')), { isAxiosError: jest.fn() })));
14
+ jest.mock('../http/axios-client');
15
+ jest.mock('../logger/logger');
16
+ const mockAxiosClient = axios_client_1.axiosClient;
17
+ const mockIsAxiosError = axios_1.default.isAxiosError;
18
+ const mockSerializeAxiosError = logger_1.serializeAxiosError;
19
+ describe('installInitialDomainMapping', () => {
20
+ // Create mock objects
21
+ const mockEvent = (0, test_helpers_1.createEvent)({ eventType: extraction_1.EventType.ExtractionDataStart });
22
+ const mockInitialDomainMapping = {
23
+ starting_recipe_blueprint: {
24
+ name: 'Test Recipe Blueprint',
25
+ description: 'Test description',
26
+ },
27
+ additional_mappings: {
28
+ custom_field: 'custom_value',
29
+ },
30
+ };
31
+ const mockSnapInResponse = {
32
+ data: {
33
+ snap_in: {
34
+ imports: [{ name: 'import-slug-123' }],
35
+ snap_in_version: { slug: 'snap-in-slug-123' },
36
+ },
37
+ },
38
+ };
39
+ const mockEndpoint = 'test_devrev_endpoint';
40
+ const mockToken = 'test_token';
41
+ let mockConsoleLog;
42
+ let mockConsoleWarn;
43
+ let mockConsoleError;
44
+ // Before each test, create a fresh spy.
45
+ beforeEach(() => {
46
+ // Re-initialize the spy and its mock implementation
47
+ mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => { });
48
+ mockConsoleWarn = jest.spyOn(console, 'warn').mockImplementation(() => { });
49
+ mockConsoleError = jest
50
+ .spyOn(console, 'error')
51
+ .mockImplementation(() => { });
52
+ });
53
+ // After each test, clear all mocks to prevent state from leaking.
54
+ afterEach(() => {
55
+ jest.clearAllMocks();
56
+ });
57
+ it('should successfully install initial domain mapping with recipe blueprint', async () => {
58
+ // Mock successful snap-in response
59
+ mockAxiosClient.get.mockResolvedValueOnce(mockSnapInResponse);
60
+ // Mock successful recipe blueprint creation
61
+ const mockRecipeBlueprintResponse = {
62
+ data: {
63
+ recipe_blueprint: {
64
+ id: 'recipe-blueprint-123',
65
+ },
66
+ },
67
+ };
68
+ mockAxiosClient.post.mockResolvedValueOnce(mockRecipeBlueprintResponse);
69
+ // Mock successful domain mapping installation
70
+ const mockDomainMappingResponse = {
71
+ data: {
72
+ success: true,
73
+ mapping_id: 'mapping-123',
74
+ },
75
+ };
76
+ mockAxiosClient.post.mockResolvedValueOnce(mockDomainMappingResponse);
77
+ await (0, install_initial_domain_mapping_1.installInitialDomainMapping)(mockEvent, mockInitialDomainMapping);
78
+ // Verify snap-in details request
79
+ expect(mockAxiosClient.get).toHaveBeenCalledWith(`${mockEndpoint}/internal/snap-ins.get`, {
80
+ headers: {
81
+ Authorization: mockToken,
82
+ },
83
+ params: {
84
+ id: 'test_snap_in_id',
85
+ },
86
+ });
87
+ // Verify recipe blueprint creation
88
+ expect(mockAxiosClient.post).toHaveBeenCalledWith(`${mockEndpoint}/internal/airdrop.recipe.blueprints.create`, {
89
+ name: 'Test Recipe Blueprint',
90
+ description: 'Test description',
91
+ }, {
92
+ headers: {
93
+ Authorization: mockToken,
94
+ },
95
+ });
96
+ // Verify domain mapping installation
97
+ expect(mockAxiosClient.post).toHaveBeenCalledWith(`${mockEndpoint}/internal/airdrop.recipe.initial-domain-mappings.install`, {
98
+ external_system_type: 'ADaaS',
99
+ import_slug: 'import-slug-123',
100
+ snap_in_slug: 'snap-in-slug-123',
101
+ starting_recipe_blueprint: 'recipe-blueprint-123',
102
+ custom_field: 'custom_value',
103
+ }, {
104
+ headers: {
105
+ Authorization: mockToken,
106
+ },
107
+ });
108
+ expect(mockConsoleLog).toHaveBeenCalledWith('Successfully created recipe blueprint with id: recipe-blueprint-123');
109
+ expect(mockConsoleLog).toHaveBeenCalledWith(`Successfully installed initial domain mapping ${JSON.stringify(mockDomainMappingResponse.data)}`);
110
+ });
111
+ it('should successfully install without recipe blueprint when not provided', async () => {
112
+ const mappingWithoutBlueprint = {
113
+ additional_mappings: {
114
+ custom_field: 'custom_value',
115
+ },
116
+ };
117
+ mockAxiosClient.get.mockResolvedValueOnce(mockSnapInResponse);
118
+ const mockDomainMappingResponse = {
119
+ data: { success: true },
120
+ };
121
+ mockAxiosClient.post.mockResolvedValueOnce(mockDomainMappingResponse);
122
+ await (0, install_initial_domain_mapping_1.installInitialDomainMapping)(mockEvent, mappingWithoutBlueprint);
123
+ // Should only make one POST request (no recipe blueprint creation)
124
+ expect(mockAxiosClient.post).toHaveBeenCalledTimes(1);
125
+ expect(mockAxiosClient.post).toHaveBeenCalledWith(`${mockEndpoint}/internal/airdrop.recipe.initial-domain-mappings.install`, {
126
+ external_system_type: 'ADaaS',
127
+ import_slug: 'import-slug-123',
128
+ snap_in_slug: 'snap-in-slug-123',
129
+ custom_field: 'custom_value',
130
+ }, {
131
+ headers: {
132
+ Authorization: mockToken,
133
+ },
134
+ });
135
+ });
136
+ it('should handle empty starting_recipe_blueprint object', async () => {
137
+ const mappingWithEmptyBlueprint = {
138
+ starting_recipe_blueprint: {},
139
+ additional_mappings: {
140
+ custom_field: 'custom_value',
141
+ },
142
+ };
143
+ mockAxiosClient.get.mockResolvedValueOnce(mockSnapInResponse);
144
+ const mockDomainMappingResponse = {
145
+ data: { success: true },
146
+ };
147
+ mockAxiosClient.post.mockResolvedValueOnce(mockDomainMappingResponse);
148
+ await (0, install_initial_domain_mapping_1.installInitialDomainMapping)(mockEvent, mappingWithEmptyBlueprint);
149
+ // Should only make one POST request (no recipe blueprint creation for empty object)
150
+ expect(mockAxiosClient.post).toHaveBeenCalledTimes(1);
151
+ });
152
+ it('should return early with warning when no initial domain mapping provided', async () => {
153
+ await (0, install_initial_domain_mapping_1.installInitialDomainMapping)(mockEvent, null);
154
+ expect(mockConsoleWarn).toHaveBeenCalledWith('No initial domain mapping found.');
155
+ expect(mockAxiosClient.get).not.toHaveBeenCalled();
156
+ expect(mockAxiosClient.post).not.toHaveBeenCalled();
157
+ });
158
+ it('should return early with warning when undefined initial domain mapping provided', async () => {
159
+ await (0, install_initial_domain_mapping_1.installInitialDomainMapping)(mockEvent, undefined);
160
+ expect(mockConsoleWarn).toHaveBeenCalledWith('No initial domain mapping found.');
161
+ expect(mockAxiosClient.get).not.toHaveBeenCalled();
162
+ expect(mockAxiosClient.post).not.toHaveBeenCalled();
163
+ });
164
+ it('should throw error when import slug is missing', async () => {
165
+ const snapInResponseWithoutImport = {
166
+ data: {
167
+ snap_in: {
168
+ imports: [],
169
+ snap_in_version: { slug: 'snap-in-slug-123' },
170
+ },
171
+ },
172
+ };
173
+ mockAxiosClient.get.mockResolvedValueOnce(snapInResponseWithoutImport);
174
+ await expect((0, install_initial_domain_mapping_1.installInitialDomainMapping)(mockEvent, mockInitialDomainMapping)).rejects.toThrow('No import slug or snap-in slug found');
175
+ });
176
+ it('should throw error when snap-in slug is missing', async () => {
177
+ const snapInResponseWithoutSlug = {
178
+ data: {
179
+ snap_in: {
180
+ imports: [{ name: 'import-slug-123' }],
181
+ snap_in_version: {},
182
+ },
183
+ },
184
+ };
185
+ mockAxiosClient.get.mockResolvedValueOnce(snapInResponseWithoutSlug);
186
+ await expect((0, install_initial_domain_mapping_1.installInitialDomainMapping)(mockEvent, mockInitialDomainMapping)).rejects.toThrow('No import slug or snap-in slug found');
187
+ });
188
+ it('should handle the error during recipe blueprint creation', async () => {
189
+ mockAxiosClient.get.mockResolvedValueOnce(mockSnapInResponse);
190
+ const genericError = new Error('Generic error during blueprint creation');
191
+ // Mock axios.isAxiosError to return false
192
+ mockIsAxiosError.mockReturnValue(false);
193
+ mockAxiosClient.post.mockRejectedValueOnce(genericError);
194
+ const mockDomainMappingResponse = {
195
+ data: { success: true },
196
+ };
197
+ mockAxiosClient.post.mockResolvedValueOnce(mockDomainMappingResponse);
198
+ await (0, install_initial_domain_mapping_1.installInitialDomainMapping)(mockEvent, mockInitialDomainMapping);
199
+ // Should still proceed with domain mapping installation
200
+ expect(mockAxiosClient.post).toHaveBeenCalledTimes(2);
201
+ });
202
+ it('should propagate error from domain mapping installation', async () => {
203
+ mockAxiosClient.get.mockResolvedValueOnce(mockSnapInResponse);
204
+ // Mock successful recipe blueprint creation
205
+ const mockRecipeBlueprintResponse = {
206
+ data: {
207
+ recipe_blueprint: {
208
+ id: 'recipe-blueprint-123',
209
+ },
210
+ },
211
+ };
212
+ mockAxiosClient.post.mockResolvedValueOnce(mockRecipeBlueprintResponse);
213
+ const domainMappingError = new Error('Domain mapping installation failed');
214
+ mockAxiosClient.post.mockRejectedValueOnce(domainMappingError);
215
+ await expect((0, install_initial_domain_mapping_1.installInitialDomainMapping)(mockEvent, mockInitialDomainMapping)).rejects.toThrow('Domain mapping installation failed');
216
+ });
217
+ });
@@ -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
  });