@adaas/a-utils 0.1.10 → 0.1.12
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.
- package/README.md +87 -32
- package/dist/index.d.mts +933 -0
- package/dist/index.d.ts +933 -27
- package/dist/index.js +1786 -90
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1764 -0
- package/dist/index.mjs.map +1 -0
- package/examples/command-examples.ts +268 -0
- package/package.json +5 -3
- package/src/index.ts +70 -0
- package/src/lib/A-Command/A-Command.constants.ts +4 -0
- package/src/lib/A-Command/A-Command.entity.ts +31 -13
- package/src/lib/A-Command/A-Command.types.ts +6 -1
- package/src/lib/A-Command/README.md +645 -0
- package/src/lib/A-Logger/A-Logger.component.ts +10 -3
- package/src/lib/A-Memory/A-Memory.context.ts +15 -0
- package/src/lib/A-Polyfill/A-Polyfill.component.ts +153 -15
- package/src/lib/A-Polyfill/A-Polyfill.types.ts +54 -0
- package/src/lib/A-Polyfill/classes/A-Buffer-Polyfill.class.ts +85 -0
- package/src/lib/A-Polyfill/classes/A-Crypto-Polyfill.class.ts +87 -0
- package/src/lib/A-Polyfill/classes/A-FS-Polyfill.class.ts +61 -0
- package/src/lib/A-Polyfill/classes/A-Http-Polyfill.class.ts +100 -0
- package/src/lib/A-Polyfill/classes/A-Https-Polyfill.class.ts +100 -0
- package/src/lib/A-Polyfill/classes/A-Path-Polyfill.class.ts +97 -0
- package/src/lib/A-Polyfill/classes/A-Process-Polyfill.class.ts +73 -0
- package/src/lib/A-Polyfill/classes/A-Url-Polyfill.class.ts +88 -0
- package/tests/A-Command.test.ts +447 -2
- package/tests/A-Config.test.ts +5 -5
- package/tests/A-Memory.test.ts +189 -0
- package/tests/A-Polyfill.test.ts +446 -29
- package/tsconfig.json +1 -1
- package/tsup.config.ts +15 -0
- package/dist/src/constants/errors.constants.d.ts +0 -0
- package/dist/src/constants/errors.constants.js +0 -2
- package/dist/src/constants/errors.constants.js.map +0 -1
- package/dist/src/lib/A-Channel/A-Channel.component.d.ts +0 -22
- package/dist/src/lib/A-Channel/A-Channel.component.js +0 -84
- package/dist/src/lib/A-Channel/A-Channel.component.js.map +0 -1
- package/dist/src/lib/A-Channel/A-Channel.error.d.ts +0 -4
- package/dist/src/lib/A-Channel/A-Channel.error.js +0 -9
- package/dist/src/lib/A-Channel/A-Channel.error.js.map +0 -1
- package/dist/src/lib/A-Channel/A-Channel.types.d.ts +0 -0
- package/dist/src/lib/A-Channel/A-Channel.types.js +0 -2
- package/dist/src/lib/A-Channel/A-Channel.types.js.map +0 -1
- package/dist/src/lib/A-Command/A-Command.constants.d.ts +0 -22
- package/dist/src/lib/A-Command/A-Command.constants.js +0 -28
- package/dist/src/lib/A-Command/A-Command.constants.js.map +0 -1
- package/dist/src/lib/A-Command/A-Command.entity.d.ts +0 -133
- package/dist/src/lib/A-Command/A-Command.entity.js +0 -273
- package/dist/src/lib/A-Command/A-Command.entity.js.map +0 -1
- package/dist/src/lib/A-Command/A-Command.error.d.ts +0 -3
- package/dist/src/lib/A-Command/A-Command.error.js +0 -8
- package/dist/src/lib/A-Command/A-Command.error.js.map +0 -1
- package/dist/src/lib/A-Command/A-Command.types.d.ts +0 -73
- package/dist/src/lib/A-Command/A-Command.types.js +0 -4
- package/dist/src/lib/A-Command/A-Command.types.js.map +0 -1
- package/dist/src/lib/A-Config/A-Config.constants.d.ts +0 -3
- package/dist/src/lib/A-Config/A-Config.constants.js +0 -6
- package/dist/src/lib/A-Config/A-Config.constants.js.map +0 -1
- package/dist/src/lib/A-Config/A-Config.container.d.ts +0 -6
- package/dist/src/lib/A-Config/A-Config.container.js +0 -77
- package/dist/src/lib/A-Config/A-Config.container.js.map +0 -1
- package/dist/src/lib/A-Config/A-Config.context.d.ts +0 -29
- package/dist/src/lib/A-Config/A-Config.context.js +0 -63
- package/dist/src/lib/A-Config/A-Config.context.js.map +0 -1
- package/dist/src/lib/A-Config/A-Config.error.d.ts +0 -4
- package/dist/src/lib/A-Config/A-Config.error.js +0 -9
- package/dist/src/lib/A-Config/A-Config.error.js.map +0 -1
- package/dist/src/lib/A-Config/A-Config.types.d.ts +0 -19
- package/dist/src/lib/A-Config/A-Config.types.js +0 -7
- package/dist/src/lib/A-Config/A-Config.types.js.map +0 -1
- package/dist/src/lib/A-Config/components/ConfigReader.component.d.ts +0 -30
- package/dist/src/lib/A-Config/components/ConfigReader.component.js +0 -103
- package/dist/src/lib/A-Config/components/ConfigReader.component.js.map +0 -1
- package/dist/src/lib/A-Config/components/ENVConfigReader.component.d.ts +0 -14
- package/dist/src/lib/A-Config/components/ENVConfigReader.component.js +0 -72
- package/dist/src/lib/A-Config/components/ENVConfigReader.component.js.map +0 -1
- package/dist/src/lib/A-Config/components/FileConfigReader.component.d.ts +0 -11
- package/dist/src/lib/A-Config/components/FileConfigReader.component.js +0 -47
- package/dist/src/lib/A-Config/components/FileConfigReader.component.js.map +0 -1
- package/dist/src/lib/A-Logger/A-Logger.component.d.ts +0 -29
- package/dist/src/lib/A-Logger/A-Logger.component.js +0 -152
- package/dist/src/lib/A-Logger/A-Logger.component.js.map +0 -1
- package/dist/src/lib/A-Logger/A-Logger.types.d.ts +0 -0
- package/dist/src/lib/A-Logger/A-Logger.types.js +0 -2
- package/dist/src/lib/A-Logger/A-Logger.types.js.map +0 -1
- package/dist/src/lib/A-Manifest/A-Manifest.context.d.ts +0 -52
- package/dist/src/lib/A-Manifest/A-Manifest.context.js +0 -154
- package/dist/src/lib/A-Manifest/A-Manifest.context.js.map +0 -1
- package/dist/src/lib/A-Manifest/A-Manifest.error.d.ts +0 -4
- package/dist/src/lib/A-Manifest/A-Manifest.error.js +0 -9
- package/dist/src/lib/A-Manifest/A-Manifest.error.js.map +0 -1
- package/dist/src/lib/A-Manifest/A-Manifest.types.d.ts +0 -43
- package/dist/src/lib/A-Manifest/A-Manifest.types.js +0 -3
- package/dist/src/lib/A-Manifest/A-Manifest.types.js.map +0 -1
- package/dist/src/lib/A-Manifest/classes/A-ManifestChecker.class.d.ts +0 -14
- package/dist/src/lib/A-Manifest/classes/A-ManifestChecker.class.js +0 -24
- package/dist/src/lib/A-Manifest/classes/A-ManifestChecker.class.js.map +0 -1
- package/dist/src/lib/A-Memory/A-Memory.context.d.ts +0 -64
- package/dist/src/lib/A-Memory/A-Memory.context.js +0 -105
- package/dist/src/lib/A-Memory/A-Memory.context.js.map +0 -1
- package/dist/src/lib/A-Polyfill/A-Polyfill.component.d.ts +0 -20
- package/dist/src/lib/A-Polyfill/A-Polyfill.component.js +0 -53
- package/dist/src/lib/A-Polyfill/A-Polyfill.component.js.map +0 -1
- package/dist/src/lib/A-Polyfill/A-Polyfill.types.d.ts +0 -9
- package/dist/src/lib/A-Polyfill/A-Polyfill.types.js +0 -3
- package/dist/src/lib/A-Polyfill/A-Polyfill.types.js.map +0 -1
- package/dist/src/lib/A-Polyfill/A-Polyfills.class.d.ts +0 -11
- package/dist/src/lib/A-Polyfill/A-Polyfills.class.js +0 -123
- package/dist/src/lib/A-Polyfill/A-Polyfills.class.js.map +0 -1
- package/dist/src/lib/A-Schedule/A-Deferred.class.d.ts +0 -12
- package/dist/src/lib/A-Schedule/A-Deferred.class.js +0 -23
- package/dist/src/lib/A-Schedule/A-Deferred.class.js.map +0 -1
- package/dist/src/lib/A-Schedule/A-Schedule.component.d.ts +0 -57
- package/dist/src/lib/A-Schedule/A-Schedule.component.js +0 -49
- package/dist/src/lib/A-Schedule/A-Schedule.component.js.map +0 -1
- package/dist/src/lib/A-Schedule/A-Schedule.types.d.ts +0 -10
- package/dist/src/lib/A-Schedule/A-Schedule.types.js +0 -3
- package/dist/src/lib/A-Schedule/A-Schedule.types.js.map +0 -1
- package/dist/src/lib/A-Schedule/A-ScheduleObject.class.d.ts +0 -29
- package/dist/src/lib/A-Schedule/A-ScheduleObject.class.js +0 -58
- package/dist/src/lib/A-Schedule/A-ScheduleObject.class.js.map +0 -1
- package/index.ts +0 -71
- package/src/lib/A-Polyfill/A-Polyfills.class.ts +0 -99
- package/tsconfig.build.json +0 -56
package/tests/A-Command.test.ts
CHANGED
|
@@ -16,7 +16,7 @@ describe('A-Command tests', () => {
|
|
|
16
16
|
expect(command.code).toBe('a-command');
|
|
17
17
|
expect(command.id).toBeDefined();
|
|
18
18
|
expect(command.aseid).toBeDefined();
|
|
19
|
-
expect(command.status).toBe(A_CONSTANTS__A_Command_Status.
|
|
19
|
+
expect(command.status).toBe(A_CONSTANTS__A_Command_Status.CREATED);
|
|
20
20
|
expect(command.scope).toBeInstanceOf(A_Scope);
|
|
21
21
|
expect(command.scope.resolve(A_Memory)).toBeInstanceOf(A_Memory);
|
|
22
22
|
});
|
|
@@ -30,6 +30,30 @@ describe('A-Command tests', () => {
|
|
|
30
30
|
expect(command.startedAt).toBeInstanceOf(Date);
|
|
31
31
|
expect(command.endedAt).toBeInstanceOf(Date);
|
|
32
32
|
});
|
|
33
|
+
it('Should Allow to create a command with custom generic types', async () => {
|
|
34
|
+
type LifecycleEvents = 'A_CUSTOM_EVENT_1' | 'A_CUSTOM_EVENT_2';
|
|
35
|
+
|
|
36
|
+
class MyCommand extends A_Command<
|
|
37
|
+
{ foo: string },
|
|
38
|
+
{ bar: string },
|
|
39
|
+
LifecycleEvents
|
|
40
|
+
> { }
|
|
41
|
+
|
|
42
|
+
const command = new MyCommand({ foo: 'baz' });
|
|
43
|
+
|
|
44
|
+
A_Context.root.register(command);
|
|
45
|
+
|
|
46
|
+
command.emit('A_CUSTOM_EVENT_1');
|
|
47
|
+
command.emit('compile');
|
|
48
|
+
|
|
49
|
+
expect(command).toBeInstanceOf(A_Command);
|
|
50
|
+
expect(command.code).toBe('my-command');
|
|
51
|
+
expect(command.id).toBeDefined();
|
|
52
|
+
expect(command.aseid).toBeDefined();
|
|
53
|
+
expect(command.status).toBe(A_CONSTANTS__A_Command_Status.CREATED);
|
|
54
|
+
expect(command.scope).toBeInstanceOf(A_Scope);
|
|
55
|
+
expect(command.scope.resolve(A_Memory)).toBeInstanceOf(A_Memory);
|
|
56
|
+
});
|
|
33
57
|
it('Should allow to serialize and deserialize a command', async () => {
|
|
34
58
|
const command = new A_Command({});
|
|
35
59
|
A_Context.root.register(command);
|
|
@@ -53,7 +77,7 @@ describe('A-Command tests', () => {
|
|
|
53
77
|
expect(deserializedCommand.startedAt?.toISOString()).toBe(command.startedAt?.toISOString());
|
|
54
78
|
expect(deserializedCommand.duration).toBe(command.duration);
|
|
55
79
|
});
|
|
56
|
-
|
|
80
|
+
|
|
57
81
|
it('Should allow to execute a command with custom logic', async () => {
|
|
58
82
|
|
|
59
83
|
// 1) create a scope
|
|
@@ -131,4 +155,425 @@ describe('A-Command tests', () => {
|
|
|
131
155
|
expect(command.errors?.size).toBe(1);
|
|
132
156
|
expect(Array.from(command.errors?.values() || [])[0].message).toBe('Test error');
|
|
133
157
|
});
|
|
158
|
+
|
|
159
|
+
describe('Command Lifecycle Tests', () => {
|
|
160
|
+
beforeEach(() => {
|
|
161
|
+
A_Context.reset();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('Should follow correct lifecycle sequence during execution', async () => {
|
|
165
|
+
const lifecycleOrder: string[] = [];
|
|
166
|
+
|
|
167
|
+
class TestCommand extends A_Command<{ input: string }, { output: string }> {}
|
|
168
|
+
|
|
169
|
+
const command = new TestCommand({ input: 'test' });
|
|
170
|
+
A_Context.root.register(command);
|
|
171
|
+
|
|
172
|
+
// Track lifecycle events
|
|
173
|
+
command.on('init', () => lifecycleOrder.push('init'));
|
|
174
|
+
command.on('compile', () => lifecycleOrder.push('compile'));
|
|
175
|
+
command.on('execute', () => lifecycleOrder.push('execute'));
|
|
176
|
+
command.on('complete', () => lifecycleOrder.push('complete'));
|
|
177
|
+
command.on('fail', () => lifecycleOrder.push('fail'));
|
|
178
|
+
|
|
179
|
+
await command.execute();
|
|
180
|
+
|
|
181
|
+
expect(lifecycleOrder).toEqual(['init', 'compile', 'execute', 'complete']);
|
|
182
|
+
expect(command.status).toBe(A_CONSTANTS__A_Command_Status.COMPLETED);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('Should track status changes through lifecycle', async () => {
|
|
186
|
+
const statusChanges: A_CONSTANTS__A_Command_Status[] = [];
|
|
187
|
+
|
|
188
|
+
class TestCommand extends A_Command<{ input: string }, { output: string }> {}
|
|
189
|
+
|
|
190
|
+
const command = new TestCommand({ input: 'test' });
|
|
191
|
+
A_Context.root.register(command);
|
|
192
|
+
|
|
193
|
+
// Initial status
|
|
194
|
+
expect(command.status).toBe(A_CONSTANTS__A_Command_Status.CREATED);
|
|
195
|
+
statusChanges.push(command.status);
|
|
196
|
+
|
|
197
|
+
await command.init();
|
|
198
|
+
expect(command.status).toBe(A_CONSTANTS__A_Command_Status.INITIALIZED);
|
|
199
|
+
statusChanges.push(command.status);
|
|
200
|
+
|
|
201
|
+
await command.compile();
|
|
202
|
+
expect(command.status).toBe(A_CONSTANTS__A_Command_Status.COMPILED);
|
|
203
|
+
statusChanges.push(command.status);
|
|
204
|
+
|
|
205
|
+
await command.complete();
|
|
206
|
+
expect(command.status).toBe(A_CONSTANTS__A_Command_Status.COMPLETED);
|
|
207
|
+
statusChanges.push(command.status);
|
|
208
|
+
|
|
209
|
+
expect(statusChanges).toEqual([
|
|
210
|
+
A_CONSTANTS__A_Command_Status.CREATED,
|
|
211
|
+
A_CONSTANTS__A_Command_Status.INITIALIZED,
|
|
212
|
+
A_CONSTANTS__A_Command_Status.COMPILED,
|
|
213
|
+
A_CONSTANTS__A_Command_Status.COMPLETED
|
|
214
|
+
]);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('Should handle failed lifecycle correctly', async () => {
|
|
218
|
+
A_Context.reset();
|
|
219
|
+
|
|
220
|
+
class FailingCommand extends A_Command<{ input: string }, { output: string }> {}
|
|
221
|
+
|
|
222
|
+
class FailingComponent extends A_Component {
|
|
223
|
+
@A_Feature.Extend({ scope: [FailingCommand] })
|
|
224
|
+
async [A_CONSTANTS_A_Command_Features.EXECUTE]() {
|
|
225
|
+
throw new A_Error({ title: 'Execution failed' });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
A_Context.root.register(FailingComponent);
|
|
230
|
+
|
|
231
|
+
const command = new FailingCommand({ input: 'test' });
|
|
232
|
+
A_Context.root.register(command);
|
|
233
|
+
|
|
234
|
+
const lifecycleOrder: string[] = [];
|
|
235
|
+
command.on('init', () => lifecycleOrder.push('init'));
|
|
236
|
+
command.on('compile', () => lifecycleOrder.push('compile'));
|
|
237
|
+
command.on('execute', () => lifecycleOrder.push('execute'));
|
|
238
|
+
command.on('complete', () => lifecycleOrder.push('complete'));
|
|
239
|
+
command.on('fail', () => lifecycleOrder.push('fail'));
|
|
240
|
+
|
|
241
|
+
await command.execute();
|
|
242
|
+
|
|
243
|
+
expect(lifecycleOrder).toEqual(['init', 'compile', 'execute', 'fail']);
|
|
244
|
+
expect(command.status).toBe(A_CONSTANTS__A_Command_Status.FAILED);
|
|
245
|
+
expect(command.isFailed).toBe(true);
|
|
246
|
+
expect(command.isCompleted).toBe(false);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('Should track execution timing correctly', async () => {
|
|
250
|
+
const command = new A_Command({});
|
|
251
|
+
A_Context.root.register(command);
|
|
252
|
+
|
|
253
|
+
expect(command.startedAt).toBeUndefined();
|
|
254
|
+
expect(command.endedAt).toBeUndefined();
|
|
255
|
+
expect(command.duration).toBeUndefined();
|
|
256
|
+
|
|
257
|
+
const startTime = Date.now();
|
|
258
|
+
await command.execute();
|
|
259
|
+
const endTime = Date.now();
|
|
260
|
+
|
|
261
|
+
expect(command.startedAt).toBeInstanceOf(Date);
|
|
262
|
+
expect(command.endedAt).toBeInstanceOf(Date);
|
|
263
|
+
expect(command.duration).toBeGreaterThanOrEqual(0);
|
|
264
|
+
expect(command.startedAt!.getTime()).toBeGreaterThanOrEqual(startTime);
|
|
265
|
+
expect(command.endedAt!.getTime()).toBeLessThanOrEqual(endTime);
|
|
266
|
+
expect(command.duration).toBe(command.endedAt!.getTime() - command.startedAt!.getTime());
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
describe('Command Subscribers/Event Listeners Tests', () => {
|
|
271
|
+
beforeEach(() => {
|
|
272
|
+
A_Context.reset();
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('Should allow multiple listeners for the same event', async () => {
|
|
276
|
+
const command = new A_Command({});
|
|
277
|
+
A_Context.root.register(command);
|
|
278
|
+
|
|
279
|
+
const listener1Calls: number[] = [];
|
|
280
|
+
const listener2Calls: number[] = [];
|
|
281
|
+
|
|
282
|
+
command.on('init', () => listener1Calls.push(1));
|
|
283
|
+
command.on('init', () => listener2Calls.push(2));
|
|
284
|
+
|
|
285
|
+
await command.init();
|
|
286
|
+
|
|
287
|
+
expect(listener1Calls).toEqual([1]);
|
|
288
|
+
expect(listener2Calls).toEqual([2]);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('Should support custom lifecycle events', async () => {
|
|
292
|
+
type CustomEvents = 'custom-event-1' | 'custom-event-2';
|
|
293
|
+
|
|
294
|
+
class CustomCommand extends A_Command<{}, {}, CustomEvents> {}
|
|
295
|
+
|
|
296
|
+
const command = new CustomCommand({});
|
|
297
|
+
A_Context.root.register(command);
|
|
298
|
+
|
|
299
|
+
const customEvent1Calls: number[] = [];
|
|
300
|
+
const customEvent2Calls: number[] = [];
|
|
301
|
+
|
|
302
|
+
command.on('custom-event-1', () => customEvent1Calls.push(1));
|
|
303
|
+
command.on('custom-event-2', () => customEvent2Calls.push(2));
|
|
304
|
+
|
|
305
|
+
command.emit('custom-event-1');
|
|
306
|
+
command.emit('custom-event-2');
|
|
307
|
+
command.emit('custom-event-1');
|
|
308
|
+
|
|
309
|
+
expect(customEvent1Calls).toEqual([1, 1]);
|
|
310
|
+
expect(customEvent2Calls).toEqual([2]);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('Should allow removing event listeners', async () => {
|
|
314
|
+
const command = new A_Command({});
|
|
315
|
+
A_Context.root.register(command);
|
|
316
|
+
|
|
317
|
+
const listenerCalls: number[] = [];
|
|
318
|
+
const listener = () => listenerCalls.push(1);
|
|
319
|
+
|
|
320
|
+
command.on('init', listener);
|
|
321
|
+
await command.init();
|
|
322
|
+
expect(listenerCalls).toEqual([1]);
|
|
323
|
+
|
|
324
|
+
// Remove listener and verify it's not called again
|
|
325
|
+
command.off('init', listener);
|
|
326
|
+
|
|
327
|
+
// Reset to call init again
|
|
328
|
+
(command as any)._status = A_CONSTANTS__A_Command_Status.CREATED;
|
|
329
|
+
await command.init();
|
|
330
|
+
expect(listenerCalls).toEqual([1]); // Should still be 1, not 2
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it('Should pass command instance to event listeners', async () => {
|
|
334
|
+
const command = new A_Command({ testParam: 'value' });
|
|
335
|
+
A_Context.root.register(command);
|
|
336
|
+
|
|
337
|
+
let receivedCommand: A_Command<any, any, any> | undefined = undefined;
|
|
338
|
+
|
|
339
|
+
command.on('init', (cmd) => {
|
|
340
|
+
receivedCommand = cmd;
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
await command.init();
|
|
344
|
+
|
|
345
|
+
expect(receivedCommand).toBe(command);
|
|
346
|
+
expect((receivedCommand as any)?.params).toEqual({ testParam: 'value' });
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it('Should propagate listener errors during event emission', async () => {
|
|
350
|
+
const command = new A_Command({});
|
|
351
|
+
A_Context.root.register(command);
|
|
352
|
+
|
|
353
|
+
const successfulCalls: number[] = [];
|
|
354
|
+
|
|
355
|
+
command.on('init', () => {
|
|
356
|
+
throw new Error('Listener error');
|
|
357
|
+
});
|
|
358
|
+
command.on('init', () => successfulCalls.push(1));
|
|
359
|
+
|
|
360
|
+
// Listener errors are propagated and will cause the command to fail
|
|
361
|
+
await expect(command.init()).rejects.toThrow('Listener error');
|
|
362
|
+
// The second listener may not be called due to the error
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
describe('Parameter Serialization and Transmission Tests', () => {
|
|
367
|
+
beforeEach(() => {
|
|
368
|
+
A_Context.reset();
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it('Should preserve complex parameter types during serialization', async () => {
|
|
372
|
+
interface ComplexParams {
|
|
373
|
+
stringParam: string;
|
|
374
|
+
numberParam: number;
|
|
375
|
+
booleanParam: boolean;
|
|
376
|
+
objectParam: {
|
|
377
|
+
nested: string;
|
|
378
|
+
array: number[];
|
|
379
|
+
};
|
|
380
|
+
arrayParam: string[];
|
|
381
|
+
dateParam: string; // ISO string representation
|
|
382
|
+
nullParam: null;
|
|
383
|
+
undefinedParam?: undefined;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const complexParams: ComplexParams = {
|
|
387
|
+
stringParam: 'test string',
|
|
388
|
+
numberParam: 42,
|
|
389
|
+
booleanParam: true,
|
|
390
|
+
objectParam: {
|
|
391
|
+
nested: 'nested value',
|
|
392
|
+
array: [1, 2, 3]
|
|
393
|
+
},
|
|
394
|
+
arrayParam: ['a', 'b', 'c'],
|
|
395
|
+
dateParam: new Date('2023-01-01').toISOString(),
|
|
396
|
+
nullParam: null
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
class ComplexCommand extends A_Command<ComplexParams, { result: string }> {}
|
|
400
|
+
|
|
401
|
+
const command = new ComplexCommand(complexParams);
|
|
402
|
+
A_Context.root.register(command);
|
|
403
|
+
|
|
404
|
+
await command.execute();
|
|
405
|
+
|
|
406
|
+
const serialized = command.toJSON();
|
|
407
|
+
expect(serialized.params).toEqual(complexParams);
|
|
408
|
+
|
|
409
|
+
// Test deserialization
|
|
410
|
+
const deserializedCommand = new ComplexCommand(serialized);
|
|
411
|
+
expect(deserializedCommand.params).toEqual(complexParams);
|
|
412
|
+
expect(deserializedCommand.params.objectParam.nested).toBe('nested value');
|
|
413
|
+
expect(deserializedCommand.params.arrayParam).toEqual(['a', 'b', 'c']);
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it('Should handle result serialization correctly', async () => {
|
|
417
|
+
A_Context.reset();
|
|
418
|
+
|
|
419
|
+
interface TestResult {
|
|
420
|
+
processedData: string;
|
|
421
|
+
count: number;
|
|
422
|
+
metadata: {
|
|
423
|
+
timestamp: string;
|
|
424
|
+
version: number;
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
class ResultCommand extends A_Command<{ input: string }, TestResult> {}
|
|
429
|
+
|
|
430
|
+
class ResultProcessor extends A_Component {
|
|
431
|
+
@A_Feature.Extend({ scope: [ResultCommand] })
|
|
432
|
+
async [A_CONSTANTS_A_Command_Features.EXECUTE](
|
|
433
|
+
@A_Inject(A_Memory) memory: A_Memory<TestResult>
|
|
434
|
+
) {
|
|
435
|
+
memory.set('processedData', 'processed-input');
|
|
436
|
+
memory.set('count', 100);
|
|
437
|
+
memory.set('metadata', {
|
|
438
|
+
timestamp: new Date().toISOString(),
|
|
439
|
+
version: 1
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
A_Context.root.register(ResultProcessor);
|
|
445
|
+
|
|
446
|
+
const command = new ResultCommand({ input: 'test-input' });
|
|
447
|
+
A_Context.root.register(command);
|
|
448
|
+
|
|
449
|
+
await command.execute();
|
|
450
|
+
|
|
451
|
+
const serialized = command.toJSON();
|
|
452
|
+
expect(serialized.result).toBeDefined();
|
|
453
|
+
expect(serialized.result?.processedData).toBe('processed-input');
|
|
454
|
+
expect(serialized.result?.count).toBe(100);
|
|
455
|
+
expect(serialized.result?.metadata).toBeDefined();
|
|
456
|
+
expect(serialized.result?.metadata.version).toBe(1);
|
|
457
|
+
|
|
458
|
+
// Test deserialization - result is restored to memory and accessible through get method
|
|
459
|
+
const deserializedCommand = new ResultCommand(serialized);
|
|
460
|
+
const deserializedMemory = deserializedCommand.scope.resolve(A_Memory);
|
|
461
|
+
expect(deserializedMemory.get('processedData')).toBe('processed-input');
|
|
462
|
+
expect(deserializedMemory.get('count')).toBe(100);
|
|
463
|
+
expect(deserializedMemory.get('metadata')).toEqual(serialized.result?.metadata);
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
it('Should handle error serialization correctly', async () => {
|
|
467
|
+
A_Context.reset();
|
|
468
|
+
|
|
469
|
+
class ErrorCommand extends A_Command<{ input: string }, { output: string }> {}
|
|
470
|
+
|
|
471
|
+
class ErrorComponent extends A_Component {
|
|
472
|
+
@A_Feature.Extend({ scope: [ErrorCommand] })
|
|
473
|
+
async [A_CONSTANTS_A_Command_Features.EXECUTE](
|
|
474
|
+
@A_Inject(A_Memory) memory: A_Memory<{ output: string }>
|
|
475
|
+
) {
|
|
476
|
+
memory.error(new A_Error({
|
|
477
|
+
title: 'First error',
|
|
478
|
+
message: 'First error message'
|
|
479
|
+
}));
|
|
480
|
+
memory.error(new A_Error({
|
|
481
|
+
title: 'Second error',
|
|
482
|
+
message: 'Second error message'
|
|
483
|
+
}));
|
|
484
|
+
throw new A_Error({ title: 'Thrown error' });
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
A_Context.root.register(ErrorComponent);
|
|
489
|
+
|
|
490
|
+
const command = new ErrorCommand({ input: 'test' });
|
|
491
|
+
A_Context.root.register(command);
|
|
492
|
+
|
|
493
|
+
await command.execute();
|
|
494
|
+
|
|
495
|
+
expect(command.isFailed).toBe(true);
|
|
496
|
+
expect(command.errors?.size).toBe(2);
|
|
497
|
+
|
|
498
|
+
const serialized = command.toJSON();
|
|
499
|
+
expect(serialized.errors).toBeDefined();
|
|
500
|
+
expect(serialized.errors?.length).toBe(2);
|
|
501
|
+
expect(serialized.errors?.[0].title).toBe('First error');
|
|
502
|
+
expect(serialized.errors?.[1].title).toBe('Second error');
|
|
503
|
+
|
|
504
|
+
// Test deserialization - errors are restored to memory
|
|
505
|
+
const deserializedCommand = new ErrorCommand(serialized);
|
|
506
|
+
const deserializedMemory = deserializedCommand.scope.resolve(A_Memory);
|
|
507
|
+
expect(deserializedMemory.Errors?.size).toBe(2);
|
|
508
|
+
const errorArray = Array.from(deserializedMemory.Errors?.values() || []);
|
|
509
|
+
expect(errorArray[0].title).toBe('First error');
|
|
510
|
+
expect(errorArray[1].title).toBe('Second error');
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
it('Should maintain parameter integrity across command transmission', async () => {
|
|
514
|
+
// Simulate command transmission across network/storage
|
|
515
|
+
const originalParams = {
|
|
516
|
+
userId: '12345',
|
|
517
|
+
action: 'update',
|
|
518
|
+
data: {
|
|
519
|
+
email: 'test@example.com',
|
|
520
|
+
preferences: {
|
|
521
|
+
theme: 'dark',
|
|
522
|
+
notifications: true
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
timestamp: new Date().toISOString()
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
class TransmissionCommand extends A_Command<typeof originalParams, { success: boolean }> {}
|
|
529
|
+
|
|
530
|
+
// Step 1: Create and execute original command
|
|
531
|
+
const originalCommand = new TransmissionCommand(originalParams);
|
|
532
|
+
A_Context.root.register(originalCommand);
|
|
533
|
+
await originalCommand.execute();
|
|
534
|
+
|
|
535
|
+
// Step 2: Serialize for transmission
|
|
536
|
+
const serializedForTransmission = JSON.stringify(originalCommand.toJSON());
|
|
537
|
+
|
|
538
|
+
// Step 3: Deserialize from transmission
|
|
539
|
+
const deserializedData = JSON.parse(serializedForTransmission);
|
|
540
|
+
const restoredCommand = new TransmissionCommand(deserializedData);
|
|
541
|
+
|
|
542
|
+
// Step 4: Verify parameter integrity
|
|
543
|
+
expect(restoredCommand.params).toEqual(originalParams);
|
|
544
|
+
expect(restoredCommand.params.data.email).toBe('test@example.com');
|
|
545
|
+
expect(restoredCommand.params.data.preferences.theme).toBe('dark');
|
|
546
|
+
expect(restoredCommand.aseid.toString()).toBe(originalCommand.aseid.toString());
|
|
547
|
+
expect(restoredCommand.code).toBe(originalCommand.code);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
it('Should handle empty and edge case parameters', async () => {
|
|
551
|
+
const edgeCaseParams = {
|
|
552
|
+
emptyString: '',
|
|
553
|
+
emptyArray: [],
|
|
554
|
+
emptyObject: {},
|
|
555
|
+
zeroNumber: 0,
|
|
556
|
+
falseBoolean: false,
|
|
557
|
+
nullValue: null
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
class EdgeCaseCommand extends A_Command<typeof edgeCaseParams, {}> {}
|
|
561
|
+
|
|
562
|
+
const command = new EdgeCaseCommand(edgeCaseParams);
|
|
563
|
+
A_Context.root.register(command);
|
|
564
|
+
await command.execute();
|
|
565
|
+
|
|
566
|
+
const serialized = command.toJSON();
|
|
567
|
+
expect(serialized.params).toEqual(edgeCaseParams);
|
|
568
|
+
|
|
569
|
+
const deserializedCommand = new EdgeCaseCommand(serialized);
|
|
570
|
+
expect(deserializedCommand.params).toEqual(edgeCaseParams);
|
|
571
|
+
expect(deserializedCommand.params.emptyString).toBe('');
|
|
572
|
+
expect(deserializedCommand.params.emptyArray).toEqual([]);
|
|
573
|
+
expect(deserializedCommand.params.emptyObject).toEqual({});
|
|
574
|
+
expect(deserializedCommand.params.zeroNumber).toBe(0);
|
|
575
|
+
expect(deserializedCommand.params.falseBoolean).toBe(false);
|
|
576
|
+
expect(deserializedCommand.params.nullValue).toBe(null);
|
|
577
|
+
});
|
|
578
|
+
});
|
|
134
579
|
});
|
package/tests/A-Config.test.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { A_Polyfill } from '@adaas/a-utils/lib/A-Polyfill/A-Polyfill.component';
|
|
|
9
9
|
import { A_ConfigLoader } from '@adaas/a-utils/lib/A-Config/A-Config.container';
|
|
10
10
|
import { ENVConfigReader } from '@adaas/a-utils/lib/A-Config/components/ENVConfigReader.component';
|
|
11
11
|
import { FileConfigReader } from '@adaas/a-utils/lib/A-Config/components/FileConfigReader.component';
|
|
12
|
-
import {
|
|
12
|
+
import { A_Logger } from '@adaas/a-utils/lib/A-Logger/A-Logger.component';
|
|
13
13
|
|
|
14
14
|
jest.retryTimes(0);
|
|
15
15
|
|
|
@@ -51,7 +51,7 @@ describe('A-Config tests', () => {
|
|
|
51
51
|
const configLoader = new A_ConfigLoader({
|
|
52
52
|
name: 'test-config-loader',
|
|
53
53
|
fragments: [config],
|
|
54
|
-
components: [A_Polyfill, FileConfigReader, ENVConfigReader]
|
|
54
|
+
components: [A_Logger, A_Polyfill, FileConfigReader, ENVConfigReader]
|
|
55
55
|
})
|
|
56
56
|
|
|
57
57
|
const concept = new A_Concept({
|
|
@@ -81,7 +81,7 @@ describe('A-Config tests', () => {
|
|
|
81
81
|
const configLoader = new A_ConfigLoader({
|
|
82
82
|
name: 'test-config-loader',
|
|
83
83
|
fragments: [config],
|
|
84
|
-
components: [A_Polyfill, ENVConfigReader]
|
|
84
|
+
components: [A_Logger, A_Polyfill, ENVConfigReader]
|
|
85
85
|
})
|
|
86
86
|
|
|
87
87
|
const concept = new A_Concept({
|
|
@@ -130,7 +130,7 @@ describe('A-Config tests', () => {
|
|
|
130
130
|
const configLoader = new A_ConfigLoader({
|
|
131
131
|
name: 'test-config-loader',
|
|
132
132
|
fragments: [config],
|
|
133
|
-
components: [A_Polyfill, FileConfigReader]
|
|
133
|
+
components: [A_Logger,A_Polyfill, FileConfigReader]
|
|
134
134
|
})
|
|
135
135
|
|
|
136
136
|
const concept = new A_Concept({
|
|
@@ -163,7 +163,7 @@ describe('A-Config tests', () => {
|
|
|
163
163
|
const configLoader = new A_ConfigLoader({
|
|
164
164
|
name: 'test-config-loader',
|
|
165
165
|
fragments: [config],
|
|
166
|
-
components: [A_Polyfill, FileConfigReader]
|
|
166
|
+
components: [A_Logger,A_Polyfill, FileConfigReader]
|
|
167
167
|
})
|
|
168
168
|
|
|
169
169
|
const concept = new A_Concept({
|