@adaas/a-utils 0.1.13 → 0.1.14
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 +46 -7
- package/dist/index.d.mts +421 -8
- package/dist/index.d.ts +421 -8
- package/dist/index.js +332 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +333 -31
- package/dist/index.mjs.map +1 -1
- package/examples/channel-examples.ts +518 -0
- package/package.json +1 -1
- package/src/lib/A-Channel/A-Channel.component.ts +516 -34
- package/src/lib/A-Channel/A-Channel.constants.ts +76 -0
- package/src/lib/A-Channel/A-Channel.error.ts +42 -1
- package/src/lib/A-Channel/A-Channel.types.ts +11 -0
- package/src/lib/A-Channel/A-ChannelRequest.context.ts +91 -0
- package/src/lib/A-Channel/README.md +864 -0
- package/tests/A-Channel.test.ts +483 -5
package/dist/index.js
CHANGED
|
@@ -13,27 +13,149 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
13
13
|
return result;
|
|
14
14
|
};
|
|
15
15
|
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
16
|
+
var A_ChannelRequestContext = class extends aConcept.A_Fragment {
|
|
17
|
+
constructor(params = {}) {
|
|
18
|
+
super();
|
|
19
|
+
this._errors = /* @__PURE__ */ new Set();
|
|
20
|
+
this._status = "PENDING" /* PENDING */;
|
|
21
|
+
this._params = params;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Returns the status of the request
|
|
25
|
+
*/
|
|
26
|
+
get status() {
|
|
27
|
+
return this._status;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Returns the parameters of the request
|
|
31
|
+
*/
|
|
32
|
+
get failed() {
|
|
33
|
+
return this._errors.size > 0;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Returns the Params of the Request
|
|
37
|
+
*/
|
|
38
|
+
get params() {
|
|
39
|
+
return this._params;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Returns the Result of the Request
|
|
43
|
+
*/
|
|
44
|
+
get data() {
|
|
45
|
+
return this._result;
|
|
46
|
+
}
|
|
47
|
+
get errors() {
|
|
48
|
+
return this._errors.size > 0 ? this._errors : void 0;
|
|
49
|
+
}
|
|
50
|
+
// ==========================================================
|
|
51
|
+
// ==================== Mutations ===========================
|
|
52
|
+
// ==========================================================
|
|
53
|
+
/**
|
|
54
|
+
* Adds an error to the context
|
|
55
|
+
*
|
|
56
|
+
* @param error
|
|
57
|
+
*/
|
|
58
|
+
fail(error) {
|
|
59
|
+
this._status = "FAILED" /* FAILED */;
|
|
60
|
+
this._errors.add(error);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Sets the result of the request
|
|
64
|
+
*
|
|
65
|
+
* @param result
|
|
66
|
+
*/
|
|
67
|
+
succeed(result) {
|
|
68
|
+
this._status = "SUCCESS" /* SUCCESS */;
|
|
69
|
+
this._result = result;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Serializes the context to a JSON object
|
|
73
|
+
*
|
|
74
|
+
* @returns
|
|
75
|
+
*/
|
|
76
|
+
toJSON() {
|
|
77
|
+
return {
|
|
78
|
+
params: this._params,
|
|
79
|
+
result: this._result,
|
|
80
|
+
status: this._status,
|
|
81
|
+
errors: this.errors ? Array.from(this._errors).map((err) => err.toString()) : void 0
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// src/lib/A-Channel/A-Channel.error.ts
|
|
16
87
|
var A_ChannelError = class extends aConcept.A_Error {
|
|
88
|
+
/**
|
|
89
|
+
* Channel Error allows to keep track of errors within a channel if something goes wrong
|
|
90
|
+
*
|
|
91
|
+
*
|
|
92
|
+
* @param originalError
|
|
93
|
+
* @param context
|
|
94
|
+
*/
|
|
95
|
+
constructor(originalError, context) {
|
|
96
|
+
if (aConcept.A_TypeGuards.isString(context))
|
|
97
|
+
super(originalError, context);
|
|
98
|
+
else
|
|
99
|
+
super(originalError);
|
|
100
|
+
if (context instanceof A_ChannelRequestContext)
|
|
101
|
+
this._context = context;
|
|
102
|
+
}
|
|
103
|
+
/***
|
|
104
|
+
* Returns Context of the error
|
|
105
|
+
*/
|
|
106
|
+
get context() {
|
|
107
|
+
return this._context;
|
|
108
|
+
}
|
|
17
109
|
};
|
|
110
|
+
// ==========================================================
|
|
111
|
+
// ==================== Error Types =========================
|
|
112
|
+
// ==========================================================
|
|
18
113
|
A_ChannelError.MethodNotImplemented = "A-Channel Method Not Implemented";
|
|
19
114
|
|
|
20
115
|
// src/lib/A-Channel/A-Channel.component.ts
|
|
21
116
|
var A_Channel = class extends aConcept.A_Component {
|
|
117
|
+
/**
|
|
118
|
+
* Creates a new A_Channel instance.
|
|
119
|
+
*
|
|
120
|
+
* The channel must be registered with A_Context before use:
|
|
121
|
+
* ```typescript
|
|
122
|
+
* const channel = new A_Channel();
|
|
123
|
+
* A_Context.root.register(channel);
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
22
126
|
constructor() {
|
|
23
|
-
super(
|
|
127
|
+
super();
|
|
24
128
|
/**
|
|
25
|
-
* Indicates whether the channel is processing requests
|
|
129
|
+
* Indicates whether the channel is currently processing requests.
|
|
130
|
+
* This flag is managed automatically during request/send operations.
|
|
131
|
+
*
|
|
132
|
+
* @readonly
|
|
26
133
|
*/
|
|
27
134
|
this._processing = false;
|
|
135
|
+
/**
|
|
136
|
+
* Internal cache storage for channel-specific data.
|
|
137
|
+
* Can be used by custom implementations for caching responses,
|
|
138
|
+
* connection pools, or other channel-specific state.
|
|
139
|
+
*
|
|
140
|
+
* @protected
|
|
141
|
+
*/
|
|
142
|
+
this._cache = /* @__PURE__ */ new Map();
|
|
28
143
|
}
|
|
29
144
|
/**
|
|
30
|
-
|
|
31
|
-
|
|
145
|
+
* Indicates whether the channel is currently processing requests.
|
|
146
|
+
*
|
|
147
|
+
* @returns {boolean} True if channel is processing, false otherwise
|
|
148
|
+
*/
|
|
32
149
|
get processing() {
|
|
33
150
|
return this._processing;
|
|
34
151
|
}
|
|
35
152
|
/**
|
|
36
|
-
*
|
|
153
|
+
* Promise that resolves when the channel is fully initialized.
|
|
154
|
+
*
|
|
155
|
+
* Automatically calls the onConnect lifecycle hook if not already called.
|
|
156
|
+
* This ensures the channel is ready for communication operations.
|
|
157
|
+
*
|
|
158
|
+
* @returns {Promise<void>} Promise that resolves when initialization is complete
|
|
37
159
|
*/
|
|
38
160
|
get initialize() {
|
|
39
161
|
if (!this._initialized) {
|
|
@@ -41,48 +163,228 @@ var A_Channel = class extends aConcept.A_Component {
|
|
|
41
163
|
}
|
|
42
164
|
return this._initialized;
|
|
43
165
|
}
|
|
166
|
+
async onConnect(...args) {
|
|
167
|
+
}
|
|
168
|
+
async onDisconnect(...args) {
|
|
169
|
+
}
|
|
170
|
+
async onBeforeRequest(...args) {
|
|
171
|
+
}
|
|
172
|
+
async onRequest(...args) {
|
|
173
|
+
}
|
|
174
|
+
async onAfterRequest(...args) {
|
|
175
|
+
}
|
|
176
|
+
async onError(...args) {
|
|
177
|
+
}
|
|
178
|
+
async onSend(...args) {
|
|
179
|
+
}
|
|
180
|
+
// ==========================================================
|
|
181
|
+
// ================= Public API Methods ===================
|
|
182
|
+
// ==========================================================
|
|
44
183
|
/**
|
|
45
|
-
* Initializes the channel
|
|
184
|
+
* Initializes the channel by calling the onConnect lifecycle hook.
|
|
185
|
+
*
|
|
186
|
+
* This method is called automatically when accessing the `initialize` property.
|
|
187
|
+
* You can also call it manually if needed.
|
|
188
|
+
*
|
|
189
|
+
* @returns {Promise<void>} Promise that resolves when connection is established
|
|
46
190
|
*/
|
|
47
191
|
async connect() {
|
|
48
|
-
|
|
49
|
-
A_ChannelError.MethodNotImplemented,
|
|
50
|
-
`The connect method is not implemented in ${this.constructor.name} channel. This method is required to initialize the channel before use. So please implement it in the derived class.`
|
|
51
|
-
);
|
|
192
|
+
await this.call("onConnect" /* onConnect */);
|
|
52
193
|
}
|
|
53
194
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
195
|
+
* Disconnects the channel by calling the onDisconnect lifecycle hook.
|
|
196
|
+
*
|
|
197
|
+
* Use this method to properly cleanup resources when the channel is no longer needed.
|
|
198
|
+
*
|
|
199
|
+
* @returns {Promise<void>} Promise that resolves when cleanup is complete
|
|
200
|
+
*/
|
|
201
|
+
async disconnect() {
|
|
202
|
+
await this.call("onDisconnect" /* onDisconnect */);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Sends a request and waits for a response (Request/Response pattern).
|
|
206
|
+
*
|
|
207
|
+
* This method follows the complete request lifecycle:
|
|
208
|
+
* 1. Ensures channel is initialized
|
|
209
|
+
* 2. Creates request scope and context
|
|
210
|
+
* 3. Calls onBeforeRequest hook
|
|
211
|
+
* 4. Calls onRequest hook (main processing)
|
|
212
|
+
* 5. Calls onAfterRequest hook
|
|
213
|
+
* 6. Returns the response context
|
|
214
|
+
*
|
|
215
|
+
* If any step fails, the onError hook is called and the error is captured
|
|
216
|
+
* in the returned context.
|
|
217
|
+
*
|
|
218
|
+
* @template _ParamsType The type of request parameters
|
|
219
|
+
* @template _ResultType The type of response data
|
|
220
|
+
* @param params The request parameters
|
|
221
|
+
* @returns {Promise<A_ChannelRequestContext<_ParamsType, _ResultType>>} Request context with response
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* // Basic usage
|
|
226
|
+
* const response = await channel.request({ action: 'getData', id: 123 });
|
|
227
|
+
*
|
|
228
|
+
* // Typed usage
|
|
229
|
+
* interface UserRequest { userId: string; }
|
|
230
|
+
* interface UserResponse { name: string; email: string; }
|
|
231
|
+
*
|
|
232
|
+
* const userResponse = await channel.request<UserRequest, UserResponse>({
|
|
233
|
+
* userId: 'user-123'
|
|
234
|
+
* });
|
|
235
|
+
*
|
|
236
|
+
* if (!userResponse.failed) {
|
|
237
|
+
* console.log('User:', userResponse.data.name);
|
|
238
|
+
* }
|
|
239
|
+
* ```
|
|
58
240
|
*/
|
|
59
241
|
async request(params) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
242
|
+
await this.initialize;
|
|
243
|
+
this._processing = true;
|
|
244
|
+
const requestScope = new aConcept.A_Scope({
|
|
245
|
+
name: `a-channel@scope:request:${aConcept.A_IdentityHelper.generateTimeId()}`
|
|
246
|
+
});
|
|
247
|
+
const context = new A_ChannelRequestContext(params);
|
|
248
|
+
try {
|
|
249
|
+
requestScope.inherit(aConcept.A_Context.scope(this));
|
|
250
|
+
requestScope.register(context);
|
|
251
|
+
await this.call("onBeforeRequest" /* onBeforeRequest */, requestScope);
|
|
252
|
+
await this.call("onRequest" /* onRequest */, requestScope);
|
|
253
|
+
await this.call("onAfterRequest" /* onAfterRequest */, requestScope);
|
|
254
|
+
this._processing = false;
|
|
255
|
+
return context;
|
|
256
|
+
} catch (error) {
|
|
257
|
+
this._processing = false;
|
|
258
|
+
const channelError = new A_ChannelError(error);
|
|
259
|
+
context.fail(channelError);
|
|
260
|
+
await this.call("onError" /* onError */, requestScope);
|
|
261
|
+
return context;
|
|
262
|
+
}
|
|
64
263
|
}
|
|
65
264
|
/**
|
|
66
|
-
*
|
|
265
|
+
* Sends a fire-and-forget message (Send pattern).
|
|
67
266
|
*
|
|
68
|
-
*
|
|
267
|
+
* This method is used for one-way communication where no response is expected:
|
|
268
|
+
* - Event broadcasting
|
|
269
|
+
* - Notification sending
|
|
270
|
+
* - Message queuing
|
|
271
|
+
* - Logging operations
|
|
272
|
+
*
|
|
273
|
+
* The method follows this lifecycle:
|
|
274
|
+
* 1. Ensures channel is initialized
|
|
275
|
+
* 2. Creates send scope and context
|
|
276
|
+
* 3. Calls onSend hook
|
|
277
|
+
* 4. Completes without returning data
|
|
278
|
+
*
|
|
279
|
+
* If the operation fails, the onError hook is called but no error is thrown
|
|
280
|
+
* to the caller (fire-and-forget semantics).
|
|
281
|
+
*
|
|
282
|
+
* @template _ParamsType The type of message parameters
|
|
283
|
+
* @param message The message to send
|
|
284
|
+
* @returns {Promise<void>} Promise that resolves when send is complete
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```typescript
|
|
288
|
+
* // Send notification
|
|
289
|
+
* await channel.send({
|
|
290
|
+
* type: 'user.login',
|
|
291
|
+
* userId: 'user-123',
|
|
292
|
+
* timestamp: new Date().toISOString()
|
|
293
|
+
* });
|
|
294
|
+
*
|
|
295
|
+
* // Send to message queue
|
|
296
|
+
* await channel.send({
|
|
297
|
+
* queue: 'email-queue',
|
|
298
|
+
* payload: {
|
|
299
|
+
* to: 'user@example.com',
|
|
300
|
+
* subject: 'Welcome!',
|
|
301
|
+
* body: 'Welcome to our service!'
|
|
302
|
+
* }
|
|
303
|
+
* });
|
|
304
|
+
* ```
|
|
69
305
|
*/
|
|
70
306
|
async send(message) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
307
|
+
await this.initialize;
|
|
308
|
+
this._processing = true;
|
|
309
|
+
const requestScope = new aConcept.A_Scope({
|
|
310
|
+
name: `a-channel@scope:send:${aConcept.A_IdentityHelper.generateTimeId()}`
|
|
311
|
+
});
|
|
312
|
+
const context = new A_ChannelRequestContext(message);
|
|
313
|
+
try {
|
|
314
|
+
requestScope.inherit(aConcept.A_Context.scope(this));
|
|
315
|
+
requestScope.register(context);
|
|
316
|
+
await this.call("onSend" /* onSend */, requestScope);
|
|
317
|
+
this._processing = false;
|
|
318
|
+
} catch (error) {
|
|
319
|
+
this._processing = false;
|
|
320
|
+
const channelError = new A_ChannelError(error);
|
|
321
|
+
context.fail(channelError);
|
|
322
|
+
await this.call("onError" /* onError */, requestScope);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* @deprecated This method is deprecated and will be removed in future versions.
|
|
327
|
+
* Use request() or send() methods instead depending on your communication pattern.
|
|
328
|
+
*
|
|
329
|
+
* For request/response pattern: Use request()
|
|
330
|
+
* For fire-and-forget pattern: Use send()
|
|
331
|
+
* For consumer patterns: Implement custom consumer logic using request() in a loop
|
|
332
|
+
*/
|
|
333
|
+
async consume() {
|
|
334
|
+
await this.initialize;
|
|
335
|
+
this._processing = true;
|
|
336
|
+
const requestScope = new aConcept.A_Scope({ name: `a-channel@scope:consume:${aConcept.A_IdentityHelper.generateTimeId()}` });
|
|
337
|
+
const context = new A_ChannelRequestContext();
|
|
338
|
+
try {
|
|
339
|
+
requestScope.inherit(aConcept.A_Context.scope(this));
|
|
340
|
+
requestScope.register(context);
|
|
341
|
+
await this.call("onConsume" /* onConsume */, requestScope);
|
|
342
|
+
this._processing = false;
|
|
343
|
+
return context;
|
|
344
|
+
} catch (error) {
|
|
345
|
+
this._processing = false;
|
|
346
|
+
const channelError = new A_ChannelError(error);
|
|
347
|
+
context.fail(channelError);
|
|
348
|
+
await this.call("onError" /* onError */, requestScope);
|
|
349
|
+
return context;
|
|
350
|
+
}
|
|
75
351
|
}
|
|
76
352
|
};
|
|
77
353
|
__decorateClass([
|
|
78
|
-
aConcept.A_Feature.
|
|
79
|
-
|
|
354
|
+
aConcept.A_Feature.Extend({
|
|
355
|
+
name: "onConnect" /* onConnect */
|
|
356
|
+
})
|
|
357
|
+
], A_Channel.prototype, "onConnect", 1);
|
|
358
|
+
__decorateClass([
|
|
359
|
+
aConcept.A_Feature.Extend({
|
|
360
|
+
name: "onDisconnect" /* onDisconnect */
|
|
361
|
+
})
|
|
362
|
+
], A_Channel.prototype, "onDisconnect", 1);
|
|
363
|
+
__decorateClass([
|
|
364
|
+
aConcept.A_Feature.Extend({
|
|
365
|
+
name: "onBeforeRequest" /* onBeforeRequest */
|
|
366
|
+
})
|
|
367
|
+
], A_Channel.prototype, "onBeforeRequest", 1);
|
|
368
|
+
__decorateClass([
|
|
369
|
+
aConcept.A_Feature.Extend({
|
|
370
|
+
name: "onRequest" /* onRequest */
|
|
371
|
+
})
|
|
372
|
+
], A_Channel.prototype, "onRequest", 1);
|
|
373
|
+
__decorateClass([
|
|
374
|
+
aConcept.A_Feature.Extend({
|
|
375
|
+
name: "onAfterRequest" /* onAfterRequest */
|
|
376
|
+
})
|
|
377
|
+
], A_Channel.prototype, "onAfterRequest", 1);
|
|
80
378
|
__decorateClass([
|
|
81
|
-
aConcept.A_Feature.
|
|
82
|
-
|
|
379
|
+
aConcept.A_Feature.Extend({
|
|
380
|
+
name: "onError" /* onError */
|
|
381
|
+
})
|
|
382
|
+
], A_Channel.prototype, "onError", 1);
|
|
83
383
|
__decorateClass([
|
|
84
|
-
aConcept.A_Feature.
|
|
85
|
-
|
|
384
|
+
aConcept.A_Feature.Extend({
|
|
385
|
+
name: "onSend" /* onSend */
|
|
386
|
+
})
|
|
387
|
+
], A_Channel.prototype, "onSend", 1);
|
|
86
388
|
|
|
87
389
|
// src/lib/A-Command/A-Command.constants.ts
|
|
88
390
|
var A_TYPES__CommandMetaKey = /* @__PURE__ */ ((A_TYPES__CommandMetaKey2) => {
|