@devrev/airsync-sdk 2.0.0-beta.3 → 2.0.0-beta.5

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 (231) hide show
  1. package/MIGRATION.md +1028 -0
  2. package/README.md +5 -11
  3. package/dist/attachments-streaming/attachments-streaming-pool.d.ts +7 -9
  4. package/dist/attachments-streaming/attachments-streaming-pool.d.ts.map +1 -1
  5. package/dist/attachments-streaming/attachments-streaming-pool.interfaces.d.ts +2 -7
  6. package/dist/attachments-streaming/attachments-streaming-pool.interfaces.d.ts.map +1 -1
  7. package/dist/attachments-streaming/attachments-streaming-pool.js +54 -56
  8. package/dist/common/constants.d.ts +4 -5
  9. package/dist/common/constants.d.ts.map +1 -1
  10. package/dist/common/constants.js +6 -7
  11. package/dist/common/helpers.d.ts +3 -35
  12. package/dist/common/helpers.d.ts.map +1 -1
  13. package/dist/common/helpers.js +5 -50
  14. package/dist/http/{axios-client-internal.d.ts → client.d.ts} +1 -1
  15. package/dist/http/client.d.ts.map +1 -0
  16. package/dist/http/{axios-client-internal.js → client.js} +4 -8
  17. package/dist/index.d.ts +24 -13
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +43 -32
  20. package/dist/logger/logger.d.ts +12 -53
  21. package/dist/logger/logger.d.ts.map +1 -1
  22. package/dist/logger/logger.interfaces.d.ts +0 -1
  23. package/dist/logger/logger.interfaces.d.ts.map +1 -1
  24. package/dist/logger/logger.js +36 -68
  25. package/dist/mappers/mappers.d.ts +7 -46
  26. package/dist/mappers/mappers.d.ts.map +1 -1
  27. package/dist/mappers/mappers.interfaces.d.ts +175 -0
  28. package/dist/mappers/mappers.interfaces.d.ts.map +1 -0
  29. package/dist/mappers/{mappers.interface.js → mappers.interfaces.js} +4 -13
  30. package/dist/mappers/mappers.js +11 -45
  31. package/dist/multithreading/adapters/base-adapter.d.ts +30 -32
  32. package/dist/multithreading/adapters/base-adapter.d.ts.map +1 -1
  33. package/dist/multithreading/adapters/base-adapter.js +97 -62
  34. package/dist/multithreading/adapters/extraction-adapter.d.ts +16 -29
  35. package/dist/multithreading/adapters/extraction-adapter.d.ts.map +1 -1
  36. package/dist/multithreading/adapters/extraction-adapter.js +203 -206
  37. package/dist/multithreading/adapters/loading-adapter.d.ts +8 -13
  38. package/dist/multithreading/adapters/loading-adapter.d.ts.map +1 -1
  39. package/dist/multithreading/adapters/loading-adapter.helpers.d.ts +2 -12
  40. package/dist/multithreading/adapters/loading-adapter.helpers.d.ts.map +1 -1
  41. package/dist/multithreading/adapters/loading-adapter.helpers.js +2 -12
  42. package/dist/multithreading/adapters/loading-adapter.js +294 -346
  43. package/dist/multithreading/emit.d.ts +11 -0
  44. package/dist/multithreading/emit.d.ts.map +1 -0
  45. package/dist/{common/control-protocol.js → multithreading/emit.js} +5 -7
  46. package/dist/multithreading/process-task.d.ts +2 -12
  47. package/dist/multithreading/process-task.d.ts.map +1 -1
  48. package/dist/multithreading/process-task.js +46 -43
  49. package/dist/multithreading/spawn/spawn.d.ts +3 -9
  50. package/dist/multithreading/spawn/spawn.d.ts.map +1 -1
  51. package/dist/multithreading/spawn/spawn.helpers.d.ts +12 -11
  52. package/dist/multithreading/spawn/spawn.helpers.d.ts.map +1 -1
  53. package/dist/multithreading/spawn/spawn.helpers.js +128 -20
  54. package/dist/multithreading/spawn/spawn.js +24 -39
  55. package/dist/multithreading/worker.js +1 -4
  56. package/dist/repo/repo.d.ts +10 -0
  57. package/dist/repo/repo.d.ts.map +1 -1
  58. package/dist/repo/repo.helpers.d.ts +6 -0
  59. package/dist/repo/repo.helpers.d.ts.map +1 -0
  60. package/dist/repo/repo.helpers.js +16 -0
  61. package/dist/repo/repo.interfaces.d.ts +4 -16
  62. package/dist/repo/repo.interfaces.d.ts.map +1 -1
  63. package/dist/repo/repo.js +23 -8
  64. package/dist/state/base-state.d.ts +16 -38
  65. package/dist/state/base-state.d.ts.map +1 -1
  66. package/dist/state/base-state.js +19 -41
  67. package/dist/state/extraction-state.d.ts +6 -21
  68. package/dist/state/extraction-state.d.ts.map +1 -1
  69. package/dist/state/extraction-state.js +8 -25
  70. package/dist/{common → state}/install-initial-domain-mapping.d.ts +1 -1
  71. package/dist/state/install-initial-domain-mapping.d.ts.map +1 -0
  72. package/dist/{common → state}/install-initial-domain-mapping.js +5 -7
  73. package/dist/state/loading-state.d.ts +3 -14
  74. package/dist/state/loading-state.d.ts.map +1 -1
  75. package/dist/state/loading-state.js +3 -14
  76. package/dist/state/state.d.ts +4 -0
  77. package/dist/state/state.d.ts.map +1 -0
  78. package/dist/state/state.interfaces.d.ts +33 -37
  79. package/dist/state/state.interfaces.d.ts.map +1 -1
  80. package/dist/state/state.interfaces.js +16 -11
  81. package/dist/state/state.js +11 -0
  82. package/dist/state/time-value-resolver.d.ts +17 -0
  83. package/dist/state/time-value-resolver.d.ts.map +1 -0
  84. package/dist/{common → state}/time-value-resolver.js +9 -41
  85. package/dist/testing/mock-event.d.ts +10 -0
  86. package/dist/testing/mock-event.d.ts.map +1 -0
  87. package/dist/{common/test-utils.js → testing/mock-event.js} +17 -14
  88. package/dist/testing/mock-server.d.ts +29 -0
  89. package/dist/testing/mock-server.d.ts.map +1 -0
  90. package/dist/testing/mock-server.interfaces.d.ts +48 -0
  91. package/dist/testing/mock-server.interfaces.d.ts.map +1 -0
  92. package/dist/{mock-server → testing}/mock-server.js +21 -33
  93. package/dist/types/common.d.ts +1 -12
  94. package/dist/types/common.d.ts.map +1 -1
  95. package/dist/types/common.js +1 -6
  96. package/dist/types/errors.d.ts +9 -0
  97. package/dist/types/errors.d.ts.map +1 -0
  98. package/dist/types/external-domain-metadata.d.ts +30 -171
  99. package/dist/types/external-domain-metadata.d.ts.map +1 -1
  100. package/dist/types/extraction.d.ts +64 -94
  101. package/dist/types/extraction.d.ts.map +1 -1
  102. package/dist/types/extraction.js +6 -34
  103. package/dist/types/loading.d.ts +1 -2
  104. package/dist/types/loading.d.ts.map +1 -1
  105. package/dist/types/loading.js +0 -1
  106. package/dist/types/workers.d.ts +39 -94
  107. package/dist/types/workers.d.ts.map +1 -1
  108. package/dist/types/workers.js +0 -6
  109. package/dist/uploader/uploader.d.ts +8 -59
  110. package/dist/uploader/uploader.d.ts.map +1 -1
  111. package/dist/uploader/uploader.helpers.d.ts +4 -27
  112. package/dist/uploader/uploader.helpers.d.ts.map +1 -1
  113. package/dist/uploader/uploader.helpers.js +64 -30
  114. package/dist/uploader/uploader.interfaces.d.ts +15 -25
  115. package/dist/uploader/uploader.interfaces.d.ts.map +1 -1
  116. package/dist/uploader/uploader.interfaces.js +8 -0
  117. package/dist/uploader/uploader.js +23 -89
  118. package/package.json +8 -6
  119. package/dist/airsync-sdk.d.ts +0 -2059
  120. package/dist/attachments-streaming/attachments-streaming-pool.test.d.ts +0 -2
  121. package/dist/attachments-streaming/attachments-streaming-pool.test.d.ts.map +0 -1
  122. package/dist/attachments-streaming/attachments-streaming-pool.test.js +0 -540
  123. package/dist/common/control-protocol.d.ts +0 -10
  124. package/dist/common/control-protocol.d.ts.map +0 -1
  125. package/dist/common/errors.d.ts +0 -6
  126. package/dist/common/errors.d.ts.map +0 -1
  127. package/dist/common/install-initial-domain-mapping.d.ts.map +0 -1
  128. package/dist/common/install-initial-domain-mapping.test.d.ts +0 -2
  129. package/dist/common/install-initial-domain-mapping.test.d.ts.map +0 -1
  130. package/dist/common/install-initial-domain-mapping.test.js +0 -211
  131. package/dist/common/test-utils.d.ts +0 -19
  132. package/dist/common/test-utils.d.ts.map +0 -1
  133. package/dist/common/time-value-resolver.d.ts +0 -47
  134. package/dist/common/time-value-resolver.d.ts.map +0 -1
  135. package/dist/common/time-value-resolver.test.d.ts +0 -2
  136. package/dist/common/time-value-resolver.test.d.ts.map +0 -1
  137. package/dist/common/time-value-resolver.test.js +0 -268
  138. package/dist/http/axios-client-internal.d.ts.map +0 -1
  139. package/dist/http/axios-client-internal.test.d.ts +0 -2
  140. package/dist/http/axios-client-internal.test.d.ts.map +0 -1
  141. package/dist/http/axios-client-internal.test.js +0 -175
  142. package/dist/http/axios-client.d.ts +0 -27
  143. package/dist/http/axios-client.d.ts.map +0 -1
  144. package/dist/http/axios-client.js +0 -60
  145. package/dist/http/constants.d.ts +0 -4
  146. package/dist/http/constants.d.ts.map +0 -1
  147. package/dist/http/constants.js +0 -6
  148. package/dist/http/index.d.ts +0 -2
  149. package/dist/http/index.d.ts.map +0 -1
  150. package/dist/http/index.js +0 -17
  151. package/dist/logger/logger.constants.d.ts +0 -6
  152. package/dist/logger/logger.constants.d.ts.map +0 -1
  153. package/dist/logger/logger.constants.js +0 -13
  154. package/dist/logger/logger.context.d.ts +0 -58
  155. package/dist/logger/logger.context.d.ts.map +0 -1
  156. package/dist/logger/logger.context.js +0 -86
  157. package/dist/logger/logger.test.d.ts +0 -2
  158. package/dist/logger/logger.test.d.ts.map +0 -1
  159. package/dist/logger/logger.test.js +0 -537
  160. package/dist/mappers/mappers.interface.d.ts +0 -294
  161. package/dist/mappers/mappers.interface.d.ts.map +0 -1
  162. package/dist/mappers/mappers.test.d.ts +0 -2
  163. package/dist/mappers/mappers.test.d.ts.map +0 -1
  164. package/dist/mappers/mappers.test.js +0 -105
  165. package/dist/mock-server/mock-server.d.ts +0 -47
  166. package/dist/mock-server/mock-server.d.ts.map +0 -1
  167. package/dist/mock-server/mock-server.interfaces.d.ts +0 -73
  168. package/dist/mock-server/mock-server.interfaces.d.ts.map +0 -1
  169. package/dist/multithreading/adapters/base-adapter.emit.test.d.ts +0 -2
  170. package/dist/multithreading/adapters/base-adapter.emit.test.d.ts.map +0 -1
  171. package/dist/multithreading/adapters/base-adapter.emit.test.js +0 -403
  172. package/dist/multithreading/adapters/extraction-adapter.artifacts.test.d.ts +0 -2
  173. package/dist/multithreading/adapters/extraction-adapter.artifacts.test.d.ts.map +0 -1
  174. package/dist/multithreading/adapters/extraction-adapter.artifacts.test.js +0 -175
  175. package/dist/multithreading/adapters/extraction-adapter.test.d.ts +0 -2
  176. package/dist/multithreading/adapters/extraction-adapter.test.d.ts.map +0 -1
  177. package/dist/multithreading/adapters/extraction-adapter.test.js +0 -789
  178. package/dist/multithreading/adapters/loading-adapter.helpers.test.d.ts +0 -2
  179. package/dist/multithreading/adapters/loading-adapter.helpers.test.d.ts.map +0 -1
  180. package/dist/multithreading/adapters/loading-adapter.helpers.test.js +0 -514
  181. package/dist/multithreading/adapters/loading-adapter.test.d.ts +0 -2
  182. package/dist/multithreading/adapters/loading-adapter.test.d.ts.map +0 -1
  183. package/dist/multithreading/adapters/loading-adapter.test.js +0 -589
  184. package/dist/multithreading/adapters/serialization.test.d.ts +0 -2
  185. package/dist/multithreading/adapters/serialization.test.d.ts.map +0 -1
  186. package/dist/multithreading/adapters/serialization.test.js +0 -71
  187. package/dist/multithreading/create-worker.test.d.ts +0 -2
  188. package/dist/multithreading/create-worker.test.d.ts.map +0 -1
  189. package/dist/multithreading/create-worker.test.js +0 -108
  190. package/dist/multithreading/process-task.test.d.ts +0 -2
  191. package/dist/multithreading/process-task.test.d.ts.map +0 -1
  192. package/dist/multithreading/process-task.test.js +0 -146
  193. package/dist/multithreading/spawn/spawn.helpers.test.d.ts +0 -2
  194. package/dist/multithreading/spawn/spawn.helpers.test.d.ts.map +0 -1
  195. package/dist/multithreading/spawn/spawn.helpers.test.js +0 -293
  196. package/dist/multithreading/spawn/spawn.test.d.ts +0 -2
  197. package/dist/multithreading/spawn/spawn.test.d.ts.map +0 -1
  198. package/dist/multithreading/spawn/spawn.test.js +0 -232
  199. package/dist/repo/repo.test.d.ts +0 -2
  200. package/dist/repo/repo.test.d.ts.map +0 -1
  201. package/dist/repo/repo.test.js +0 -184
  202. package/dist/state/state.extract-window.test.d.ts +0 -2
  203. package/dist/state/state.extract-window.test.d.ts.map +0 -1
  204. package/dist/state/state.extract-window.test.js +0 -163
  205. package/dist/state/state.pending-boundaries.test.d.ts +0 -2
  206. package/dist/state/state.pending-boundaries.test.d.ts.map +0 -1
  207. package/dist/state/state.pending-boundaries.test.js +0 -189
  208. package/dist/state/state.post-state.test.d.ts +0 -2
  209. package/dist/state/state.post-state.test.d.ts.map +0 -1
  210. package/dist/state/state.post-state.test.js +0 -78
  211. package/dist/state/state.test.d.ts +0 -2
  212. package/dist/state/state.test.d.ts.map +0 -1
  213. package/dist/state/state.test.js +0 -271
  214. package/dist/state/state.time-value-resolution.test.d.ts +0 -2
  215. package/dist/state/state.time-value-resolution.test.d.ts.map +0 -1
  216. package/dist/state/state.time-value-resolution.test.js +0 -175
  217. package/dist/tsdoc-metadata.json +0 -11
  218. package/dist/types/extraction.test.d.ts +0 -2
  219. package/dist/types/extraction.test.d.ts.map +0 -1
  220. package/dist/types/extraction.test.js +0 -96
  221. package/dist/types/index.d.ts +0 -10
  222. package/dist/types/index.d.ts.map +0 -1
  223. package/dist/types/index.js +0 -21
  224. package/dist/uploader/uploader.helpers.test.d.ts +0 -2
  225. package/dist/uploader/uploader.helpers.test.d.ts.map +0 -1
  226. package/dist/uploader/uploader.helpers.test.js +0 -256
  227. package/dist/uploader/uploader.test.d.ts +0 -2
  228. package/dist/uploader/uploader.test.d.ts.map +0 -1
  229. package/dist/uploader/uploader.test.js +0 -601
  230. /package/dist/{mock-server → testing}/mock-server.interfaces.js +0 -0
  231. /package/dist/{common → types}/errors.js +0 -0
@@ -1,589 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const loading_state_1 = require("../../state/loading-state");
4
- const jest_setup_1 = require("../../tests/jest.setup");
5
- const test_utils_1 = require("../../common/test-utils");
6
- const types_1 = require("../../types");
7
- const loading_1 = require("../../types/loading");
8
- const loading_adapter_1 = require("./loading-adapter");
9
- jest.mock('../../common/control-protocol', () => ({
10
- emit: jest.fn().mockResolvedValue({}),
11
- }));
12
- jest.mock('../../mappers/mappers');
13
- jest.mock('../../uploader/uploader');
14
- jest.mock('../../repo/repo');
15
- jest.mock('node:worker_threads', () => ({
16
- parentPort: { postMessage: jest.fn() },
17
- }));
18
- jest.mock('../../attachments-streaming/attachments-streaming-pool', () => ({
19
- AttachmentsStreamingPool: jest.fn().mockImplementation(() => ({
20
- streamAll: jest.fn().mockResolvedValue(undefined),
21
- })),
22
- }));
23
- function makeAdapter(eventType) {
24
- const event = (0, test_utils_1.createMockEvent)(jest_setup_1.mockServer.baseUrl, {
25
- payload: { event_type: eventType },
26
- });
27
- const initialState = {
28
- attachments: { completed: false },
29
- };
30
- const adapterState = new loading_state_1.LoadingState({ event, initialState });
31
- adapterState.sdkState.snapInVersionId = '';
32
- const adapter = new loading_adapter_1.LoadingAdapter({ event, adapterState });
33
- return { adapter, event, adapterState };
34
- }
35
- function makeLoaderItem(devrevId = 'dev-1') {
36
- return {
37
- id: { devrev: devrevId, external: 'ext-1' },
38
- created_date: '',
39
- modified_date: '',
40
- data: {},
41
- };
42
- }
43
- function setupLoaderFile(adapter, items, itemType = 'tasks') {
44
- adapter['adapterState'].sdkState.fromDevRev = {
45
- filesToLoad: [
46
- {
47
- id: 'artifact-1',
48
- file_name: 'file.json',
49
- itemType,
50
- count: items.length,
51
- lineToProcess: 0,
52
- completed: false,
53
- },
54
- ],
55
- };
56
- adapter['uploader'].getJsonObjectByArtifactId = jest
57
- .fn()
58
- .mockResolvedValue({ response: items });
59
- }
60
- describe(`${loading_adapter_1.LoadingAdapter.name}.loadItemTypes — timeout and unexpected errors`, () => {
61
- let adapter;
62
- let exitSpy;
63
- let emitSpy;
64
- beforeEach(() => {
65
- jest.clearAllMocks();
66
- ({ adapter } = makeAdapter(types_1.EventType.ContinueLoadingData));
67
- exitSpy = jest
68
- .spyOn(process, 'exit')
69
- .mockImplementation(() => undefined);
70
- emitSpy = jest.spyOn(adapter, 'emit').mockResolvedValue();
71
- });
72
- afterEach(() => {
73
- exitSpy.mockRestore();
74
- jest.restoreAllMocks();
75
- });
76
- it('should emit DataLoadingProgress and exit on timeout', async () => {
77
- // Arrange
78
- const items = [makeLoaderItem('dev-1'), makeLoaderItem('dev-2')];
79
- setupLoaderFile(adapter, items);
80
- adapter.isTimeout = true;
81
- const itemTypesToLoad = [
82
- { itemType: 'tasks', create: jest.fn(), update: jest.fn() },
83
- ];
84
- // Act
85
- await adapter.loadItemTypes({ itemTypesToLoad });
86
- // Assert
87
- expect(emitSpy).toHaveBeenCalledWith(types_1.LoaderEventType.DataLoadingProgress);
88
- expect(exitSpy).toHaveBeenCalledWith(0);
89
- });
90
- it('should emit DataLoadingProgress mid-loop when timeout arrives between items', async () => {
91
- // Arrange
92
- const items = [
93
- makeLoaderItem('dev-1'),
94
- makeLoaderItem('dev-2'),
95
- makeLoaderItem('dev-3'),
96
- ];
97
- setupLoaderFile(adapter, items);
98
- exitSpy.mockRestore();
99
- exitSpy = jest.spyOn(process, 'exit').mockImplementation((() => {
100
- throw new Error('process.exit');
101
- }));
102
- let loadItemCallCount = 0;
103
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/require-await
104
- jest.spyOn(adapter, 'loadItem').mockImplementation(async () => {
105
- loadItemCallCount++;
106
- if (loadItemCallCount === 1) {
107
- adapter.isTimeout = true;
108
- }
109
- return { report: { item_type: 'tasks', updated: 1 } };
110
- });
111
- const itemTypesToLoad = [
112
- { itemType: 'tasks', create: jest.fn(), update: jest.fn() },
113
- ];
114
- // Act & Assert
115
- await expect(adapter.loadItemTypes({ itemTypesToLoad })).rejects.toThrow('process.exit');
116
- expect(loadItemCallCount).toBe(1);
117
- expect(emitSpy).toHaveBeenCalledWith(types_1.LoaderEventType.DataLoadingProgress);
118
- });
119
- it('should emit DataLoadingError and exit(1) on unexpected error', async () => {
120
- // Arrange
121
- adapter['adapterState'].sdkState.fromDevRev = {
122
- filesToLoad: [
123
- {
124
- id: 'artifact-1',
125
- file_name: 'file1.json',
126
- itemType: 'tasks',
127
- count: 1,
128
- lineToProcess: 0,
129
- completed: false,
130
- },
131
- ],
132
- };
133
- adapter['uploader'].getJsonObjectByArtifactId = jest
134
- .fn()
135
- .mockRejectedValue(new Error('Unexpected network failure'));
136
- const itemTypesToLoad = [
137
- { itemType: 'tasks', create: jest.fn(), update: jest.fn() },
138
- ];
139
- // Act
140
- await adapter.loadItemTypes({ itemTypesToLoad });
141
- // Assert
142
- expect(emitSpy).toHaveBeenCalledWith(types_1.LoaderEventType.DataLoadingError, expect.objectContaining({
143
- error: expect.objectContaining({
144
- message: expect.stringContaining('Error during data loading'),
145
- }),
146
- }));
147
- expect(exitSpy).toHaveBeenCalledWith(1);
148
- });
149
- });
150
- describe(`${loading_adapter_1.LoadingAdapter.name}.loadItemTypes — loadItem branch coverage via public API`, () => {
151
- let adapter;
152
- let emitSpy;
153
- let exitSpy;
154
- const itemTypesToLoad = [
155
- { itemType: 'tasks', create: jest.fn(), update: jest.fn() },
156
- ];
157
- beforeEach(() => {
158
- jest.clearAllMocks();
159
- ({ adapter } = makeAdapter(types_1.EventType.ContinueLoadingData));
160
- emitSpy = jest.spyOn(adapter, 'emit').mockResolvedValue();
161
- exitSpy = jest
162
- .spyOn(process, 'exit')
163
- .mockImplementation(() => undefined);
164
- itemTypesToLoad[0].create = jest.fn();
165
- itemTypesToLoad[0].update = jest.fn();
166
- });
167
- afterEach(() => {
168
- exitSpy.mockRestore();
169
- jest.restoreAllMocks();
170
- });
171
- it('should accumulate an UPDATED report when the connector updates the item and the mapper sync succeeds', async () => {
172
- // Arrange
173
- setupLoaderFile(adapter, [makeLoaderItem('dev-1')]);
174
- adapter['_mappers'].getByTargetId = jest.fn().mockResolvedValue({
175
- data: { sync_mapper_record: { id: 'smr-1' } },
176
- });
177
- adapter['_mappers'].update = jest.fn().mockResolvedValue({ data: {} });
178
- itemTypesToLoad[0].update = jest
179
- .fn()
180
- .mockResolvedValue({ id: 'ext-updated-1' });
181
- // Act
182
- const { reports } = await adapter.loadItemTypes({ itemTypesToLoad });
183
- // Assert
184
- expect(reports).toEqual(expect.arrayContaining([
185
- expect.objectContaining({
186
- item_type: 'tasks',
187
- [loading_1.ActionType.UPDATED]: 1,
188
- }),
189
- ]));
190
- expect(emitSpy).not.toHaveBeenCalled();
191
- });
192
- it('should fall back to create and accumulate a CREATED report when the mapper record does not exist (404)', async () => {
193
- // Arrange
194
- setupLoaderFile(adapter, [makeLoaderItem('dev-2')]);
195
- const axiosError = { isAxiosError: true, response: { status: 404 } };
196
- adapter['_mappers'].getByTargetId = jest.fn().mockRejectedValue(axiosError);
197
- adapter['_mappers'].create = jest.fn().mockResolvedValue({ data: {} });
198
- itemTypesToLoad[0].create = jest
199
- .fn()
200
- .mockResolvedValue({ id: 'new-ext-id' });
201
- // Act
202
- const { reports } = await adapter.loadItemTypes({ itemTypesToLoad });
203
- // Assert
204
- expect(reports).toEqual(expect.arrayContaining([
205
- expect.objectContaining({
206
- item_type: 'tasks',
207
- [loading_1.ActionType.CREATED]: 1,
208
- }),
209
- ]));
210
- expect(emitSpy).not.toHaveBeenCalled();
211
- });
212
- it('should emit DataLoadingDelayed and stop processing when the connector signals a rate-limit delay', async () => {
213
- // Arrange
214
- setupLoaderFile(adapter, [makeLoaderItem('dev-3')]);
215
- adapter['_mappers'].getByTargetId = jest.fn().mockResolvedValue({
216
- data: { sync_mapper_record: { id: 'smr-1' } },
217
- });
218
- itemTypesToLoad[0].update = jest.fn().mockResolvedValue({ delay: 15 });
219
- // Act
220
- await adapter.loadItemTypes({ itemTypesToLoad });
221
- // Assert
222
- expect(emitSpy).toHaveBeenCalledWith(types_1.LoaderEventType.DataLoadingDelayed, expect.objectContaining({ delay: 15 }));
223
- });
224
- it('should count the item as FAILED when the update succeeds but the mapper sync throws', async () => {
225
- // Arrange
226
- setupLoaderFile(adapter, [makeLoaderItem('dev-4')]);
227
- adapter['_mappers'].getByTargetId = jest.fn().mockResolvedValue({
228
- data: { sync_mapper_record: { id: 'smr-1' } },
229
- });
230
- adapter['_mappers'].update = jest
231
- .fn()
232
- .mockRejectedValue(new Error('mapper down'));
233
- itemTypesToLoad[0].update = jest.fn().mockResolvedValue({ id: 'ext-id' });
234
- // Act
235
- const { reports } = await adapter.loadItemTypes({ itemTypesToLoad });
236
- // Assert
237
- expect(emitSpy).not.toHaveBeenCalled();
238
- expect(reports).toBeDefined();
239
- });
240
- it('should not emit for a non-404 Axios error from the mapper (recorded as item-level error)', async () => {
241
- // Arrange
242
- setupLoaderFile(adapter, [makeLoaderItem('dev-5')]);
243
- const axiosError = {
244
- isAxiosError: true,
245
- message: 'internal server error',
246
- response: { status: 500 },
247
- };
248
- adapter['_mappers'].getByTargetId = jest.fn().mockRejectedValue(axiosError);
249
- // Act
250
- await adapter.loadItemTypes({ itemTypesToLoad });
251
- // Assert
252
- expect(emitSpy).not.toHaveBeenCalled();
253
- });
254
- it('should handle a null sync_mapper_record gracefully and continue loading', async () => {
255
- // Arrange
256
- setupLoaderFile(adapter, [makeLoaderItem('dev-6')]);
257
- adapter['_mappers'].getByTargetId = jest
258
- .fn()
259
- .mockResolvedValue({ data: null });
260
- // Act
261
- const { reports } = await adapter.loadItemTypes({ itemTypesToLoad });
262
- // Assert
263
- expect(emitSpy).not.toHaveBeenCalled();
264
- expect(reports).toBeDefined();
265
- });
266
- });
267
- describe(`${loading_adapter_1.LoadingAdapter.name}.loadItemTypes — additional branches`, () => {
268
- let adapter;
269
- let emitSpy;
270
- beforeEach(() => {
271
- jest.clearAllMocks();
272
- ({ adapter } = makeAdapter(types_1.EventType.ContinueLoadingData));
273
- emitSpy = jest.spyOn(adapter, 'emit').mockResolvedValue();
274
- });
275
- afterEach(() => {
276
- jest.restoreAllMocks();
277
- });
278
- it('should return immediately with empty reports when filesToLoad is empty', async () => {
279
- // Arrange
280
- adapter['adapterState'].sdkState.fromDevRev = { filesToLoad: [] };
281
- // Act
282
- const result = await adapter.loadItemTypes({
283
- itemTypesToLoad: [
284
- { itemType: 'tasks', create: jest.fn(), update: jest.fn() },
285
- ],
286
- });
287
- // Assert
288
- expect(result.reports).toEqual([]);
289
- expect(emitSpy).not.toHaveBeenCalled();
290
- });
291
- it('should emit DataLoadingError when a file references an item type not in itemTypesToLoad', async () => {
292
- // Arrange
293
- adapter['adapterState'].sdkState.fromDevRev = {
294
- filesToLoad: [
295
- {
296
- id: 'art-1',
297
- file_name: 'file.json',
298
- itemType: 'unknown-type',
299
- count: 1,
300
- lineToProcess: 0,
301
- completed: false,
302
- },
303
- ],
304
- };
305
- adapter['uploader'].getJsonObjectByArtifactId = jest
306
- .fn()
307
- .mockResolvedValue({ response: [makeLoaderItem()] });
308
- // Act
309
- await adapter.loadItemTypes({
310
- itemTypesToLoad: [
311
- { itemType: 'tasks', create: jest.fn(), update: jest.fn() },
312
- ],
313
- });
314
- // Assert
315
- expect(emitSpy).toHaveBeenCalledWith(types_1.LoaderEventType.DataLoadingError, expect.objectContaining({
316
- error: expect.objectContaining({
317
- message: expect.stringContaining('unknown-type'),
318
- }),
319
- }));
320
- });
321
- });
322
- describe(`${loading_adapter_1.LoadingAdapter.name}.loadAttachments — timeout, transformer errors, unexpected errors`, () => {
323
- let adapter;
324
- let exitSpy;
325
- let emitSpy;
326
- function setupFilesToLoad(a, items) {
327
- a['adapterState'].sdkState.fromDevRev = {
328
- filesToLoad: [
329
- {
330
- id: 'artifact-1',
331
- file_name: 'attachments.json',
332
- itemType: 'attachment',
333
- count: items.length,
334
- lineToProcess: 0,
335
- completed: false,
336
- },
337
- ],
338
- };
339
- a['uploader'].getJsonObjectByArtifactId = jest
340
- .fn()
341
- .mockResolvedValue({ response: items });
342
- }
343
- beforeEach(() => {
344
- jest.clearAllMocks();
345
- ({ adapter } = makeAdapter(types_1.EventType.ContinueLoadingAttachments));
346
- exitSpy = jest
347
- .spyOn(process, 'exit')
348
- .mockImplementation(() => undefined);
349
- emitSpy = jest.spyOn(adapter, 'emit').mockResolvedValue();
350
- });
351
- afterEach(() => {
352
- exitSpy.mockRestore();
353
- jest.restoreAllMocks();
354
- });
355
- it('should emit AttachmentLoadingProgress and exit on timeout', async () => {
356
- // Arrange
357
- const items = [
358
- {
359
- reference_id: 'ref-1',
360
- parent_type: 'task',
361
- parent_reference_id: 'parent-1',
362
- file_name: 'file.pdf',
363
- file_type: 'application/pdf',
364
- file_size: 100,
365
- url: 'https://example.com/file.pdf',
366
- valid_until: '',
367
- created_by_id: 'user-1',
368
- created_date: '',
369
- modified_by_id: 'user-1',
370
- modified_date: '',
371
- },
372
- ];
373
- setupFilesToLoad(adapter, items);
374
- adapter.isTimeout = true;
375
- // Act
376
- await adapter.loadAttachments({
377
- create: jest.fn(),
378
- });
379
- // Assert
380
- expect(emitSpy).toHaveBeenCalledWith(types_1.LoaderEventType.AttachmentLoadingProgress);
381
- expect(exitSpy).toHaveBeenCalledWith(0);
382
- });
383
- it('should emit AttachmentLoadingError on transformer file error', async () => {
384
- // Arrange
385
- adapter['adapterState'].sdkState.fromDevRev = {
386
- filesToLoad: [
387
- {
388
- id: 'bad-artifact',
389
- file_name: 'attachments.json',
390
- itemType: 'attachment',
391
- count: 1,
392
- lineToProcess: 0,
393
- completed: false,
394
- },
395
- ],
396
- };
397
- adapter['uploader'].getJsonObjectByArtifactId = jest
398
- .fn()
399
- .mockResolvedValue({
400
- response: null,
401
- error: new Error('Artifact not found'),
402
- });
403
- // Act
404
- await adapter.loadAttachments({
405
- create: jest.fn(),
406
- });
407
- // Assert
408
- expect(emitSpy).toHaveBeenCalledWith(types_1.LoaderEventType.AttachmentLoadingError, expect.objectContaining({
409
- error: expect.objectContaining({
410
- message: expect.stringContaining('Transformer file not found'),
411
- }),
412
- }));
413
- });
414
- it('should emit AttachmentLoadingError and exit(1) on unexpected error', async () => {
415
- // Arrange
416
- const items = [
417
- {
418
- reference_id: 'ref-1',
419
- parent_type: 'task',
420
- parent_reference_id: 'parent-1',
421
- file_name: 'file.pdf',
422
- file_type: 'application/pdf',
423
- file_size: 100,
424
- url: 'https://example.com/file.pdf',
425
- valid_until: '',
426
- created_by_id: 'user-1',
427
- created_date: '',
428
- modified_by_id: 'user-1',
429
- modified_date: '',
430
- },
431
- ];
432
- setupFilesToLoad(adapter, items);
433
- const mockCreate = jest
434
- .fn()
435
- .mockRejectedValue(new Error('Unexpected API failure'));
436
- // Act
437
- await adapter.loadAttachments({ create: mockCreate });
438
- // Assert
439
- expect(emitSpy).toHaveBeenCalledWith(types_1.LoaderEventType.AttachmentLoadingError, expect.objectContaining({
440
- error: expect.objectContaining({
441
- message: expect.stringContaining('Error during attachment loading'),
442
- }),
443
- }));
444
- expect(exitSpy).toHaveBeenCalledWith(1);
445
- });
446
- });
447
- describe(`${loading_adapter_1.LoadingAdapter.name}.loadAttachments — additional branches`, () => {
448
- let adapter;
449
- let emitSpy;
450
- beforeEach(() => {
451
- jest.clearAllMocks();
452
- ({ adapter } = makeAdapter(types_1.EventType.ContinueLoadingAttachments));
453
- emitSpy = jest.spyOn(adapter, 'emit').mockResolvedValue();
454
- });
455
- afterEach(() => {
456
- jest.restoreAllMocks();
457
- });
458
- it('should return immediately with empty reports when fromDevRev is not set', async () => {
459
- // Arrange
460
- adapter['adapterState'].sdkState.fromDevRev = undefined;
461
- // Act
462
- const result = await adapter.loadAttachments({ create: jest.fn() });
463
- // Assert
464
- expect(result.reports).toEqual([]);
465
- expect(emitSpy).not.toHaveBeenCalled();
466
- });
467
- it('should emit AttachmentLoadingDelayed and stop the loop when the connector signals a rate-limit delay', async () => {
468
- // Arrange
469
- adapter['adapterState'].sdkState.fromDevRev = {
470
- filesToLoad: [
471
- {
472
- id: 'art-1',
473
- file_name: 'attachments.json',
474
- itemType: 'attachment',
475
- count: 1,
476
- lineToProcess: 0,
477
- completed: false,
478
- },
479
- ],
480
- };
481
- adapter['uploader'].getJsonObjectByArtifactId = jest
482
- .fn()
483
- .mockResolvedValue({
484
- response: [
485
- {
486
- reference_id: 'ref-1',
487
- parent_type: 'task',
488
- parent_reference_id: 'parent-1',
489
- file_name: 'file.pdf',
490
- file_type: 'application/pdf',
491
- file_size: 100,
492
- url: 'https://example.com/file.pdf',
493
- valid_until: '',
494
- created_by_id: 'user-1',
495
- created_date: '',
496
- modified_by_id: 'user-1',
497
- modified_date: '',
498
- },
499
- ],
500
- });
501
- jest
502
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
503
- .spyOn(adapter, 'loadAttachment')
504
- .mockResolvedValue({ rateLimit: { delay: 20 } });
505
- // Act
506
- await adapter.loadAttachments({ create: jest.fn() });
507
- // Assert
508
- expect(emitSpy).toHaveBeenCalledWith(types_1.LoaderEventType.AttachmentLoadingDelayed, expect.objectContaining({ delay: 20 }));
509
- });
510
- });
511
- describe(`${loading_adapter_1.LoadingAdapter.name}.loadAttachment`, () => {
512
- let adapter;
513
- beforeEach(() => {
514
- jest.clearAllMocks();
515
- ({ adapter } = makeAdapter(types_1.EventType.ContinueLoadingAttachments));
516
- });
517
- afterEach(() => {
518
- jest.restoreAllMocks();
519
- });
520
- function makeAttachment() {
521
- return {
522
- reference_id: 'ref-1',
523
- parent_type: 'task',
524
- parent_reference_id: 'parent-1',
525
- file_name: 'file.pdf',
526
- file_type: 'application/pdf',
527
- file_size: 100,
528
- url: 'https://example.com/file.pdf',
529
- valid_until: '',
530
- created_by_id: 'user-1',
531
- created_date: '',
532
- modified_by_id: 'user-1',
533
- modified_date: '',
534
- };
535
- }
536
- it('should return a CREATED report when create succeeds', async () => {
537
- var _a, _b;
538
- // Arrange
539
- adapter['_mappers'].create = jest.fn().mockResolvedValue({ data: {} });
540
- const create = jest.fn().mockResolvedValue({ id: 'att-ext-1' });
541
- // Act
542
- const result = await adapter['loadAttachment']({
543
- item: makeAttachment(),
544
- create,
545
- });
546
- // Assert
547
- expect((_a = result.report) === null || _a === void 0 ? void 0 : _a.item_type).toBe('attachment');
548
- expect((_b = result.report) === null || _b === void 0 ? void 0 : _b[loading_1.ActionType.CREATED]).toBe(1);
549
- });
550
- it('should still return CREATED even when mapper create fails — attachment loading is resilient', async () => {
551
- var _a;
552
- // Arrange
553
- adapter['_mappers'].create = jest
554
- .fn()
555
- .mockRejectedValue(new Error('mapper failed'));
556
- const create = jest.fn().mockResolvedValue({ id: 'att-ext-1' });
557
- // Act
558
- const result = await adapter['loadAttachment']({
559
- item: makeAttachment(),
560
- create,
561
- });
562
- // Assert
563
- expect((_a = result.report) === null || _a === void 0 ? void 0 : _a[loading_1.ActionType.CREATED]).toBe(1);
564
- });
565
- it('should propagate rate-limit delay when the connector signals one', async () => {
566
- var _a;
567
- // Arrange
568
- const create = jest.fn().mockResolvedValue({ delay: 30 });
569
- // Act
570
- const result = await adapter['loadAttachment']({
571
- item: makeAttachment(),
572
- create,
573
- });
574
- // Assert
575
- expect((_a = result.rateLimit) === null || _a === void 0 ? void 0 : _a.delay).toBe(30);
576
- });
577
- it('should return a FAILED report when create returns neither id nor delay', async () => {
578
- var _a;
579
- // Arrange
580
- const create = jest.fn().mockResolvedValue({ id: null, delay: null });
581
- // Act
582
- const result = await adapter['loadAttachment']({
583
- item: makeAttachment(),
584
- create,
585
- });
586
- // Assert
587
- expect((_a = result.report) === null || _a === void 0 ? void 0 : _a[loading_1.ActionType.FAILED]).toBe(1);
588
- });
589
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=serialization.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"serialization.test.d.ts","sourceRoot":"","sources":["../../../src/multithreading/adapters/serialization.test.ts"],"names":[],"mappings":""}
@@ -1,71 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const js_jsonl_1 = require("js-jsonl");
4
- // Pin the serialization contract for items that reach the uploader.
5
- //
6
- // The SDK uploads items via Uploader.upload(), which calls jsonl.stringify() on
7
- // the input. That means user `create`/`update` callbacks and normalizers can
8
- // silently produce inputs that fail or lose information at the wire boundary:
9
- //
10
- // - Circular references throw "Converting circular structure to JSON"
11
- // - BigInt values throw "Do not know how to serialize a BigInt"
12
- // - Date objects are converted to ISO strings (information loss: no Date on
13
- // the other side, just a string)
14
- // - undefined fields are dropped (null fields are preserved)
15
- //
16
- // These tests exist to catch regressions in the serialization layer (e.g.,
17
- // silently switching to a different serializer that masks BigInt or mangles
18
- // Dates) before they reach production.
19
- describe('serialization boundary for items uploaded via jsonl', () => {
20
- it('throws when an item contains a circular reference', () => {
21
- // Arrange
22
- const item = { id: 'a' };
23
- item.self = item;
24
- // Act & Assert
25
- expect(() => js_jsonl_1.jsonl.stringify([item])).toThrow(/circular/i);
26
- });
27
- it('throws when an item contains a BigInt field', () => {
28
- // Arrange
29
- const item = { id: 'a', counter: BigInt(1) };
30
- // Act & Assert
31
- expect(() => js_jsonl_1.jsonl.stringify([item])).toThrow(/BigInt/i);
32
- });
33
- it('serializes Date instances to ISO strings (information loss — consumer receives a string)', () => {
34
- // Arrange
35
- const item = {
36
- id: 'a',
37
- created: new Date('2025-01-01T00:00:00.000Z'),
38
- };
39
- // Act
40
- const output = js_jsonl_1.jsonl.stringify([item]);
41
- const parsed = JSON.parse(output);
42
- // Assert
43
- expect(parsed.created).toBe('2025-01-01T00:00:00.000Z');
44
- expect(typeof parsed.created).toBe('string');
45
- });
46
- it('drops undefined fields but preserves null fields', () => {
47
- // Arrange
48
- const item = {
49
- id: 'a',
50
- present: null,
51
- missing: undefined,
52
- };
53
- // Act
54
- const output = js_jsonl_1.jsonl.stringify([item]);
55
- const parsed = JSON.parse(output);
56
- // Assert
57
- expect(parsed).toEqual({ id: 'a', present: null });
58
- expect(parsed).not.toHaveProperty('missing');
59
- });
60
- it('emits one newline-terminated line per item (jsonl format)', () => {
61
- // Arrange
62
- const items = [{ id: 'a' }, { id: 'b' }, { id: 'c' }];
63
- // Act
64
- const output = js_jsonl_1.jsonl.stringify(items);
65
- const lines = output.split('\n').filter((l) => l.length > 0);
66
- // Assert
67
- expect(lines).toHaveLength(3);
68
- expect(JSON.parse(lines[0])).toEqual({ id: 'a' });
69
- expect(JSON.parse(lines[2])).toEqual({ id: 'c' });
70
- });
71
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=create-worker.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-worker.test.d.ts","sourceRoot":"","sources":["../../src/multithreading/create-worker.test.ts"],"names":[],"mappings":""}