@adaas/a-utils 0.1.12 → 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 +429 -8
- package/dist/index.d.ts +429 -8
- package/dist/index.js +369 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +370 -40
- 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/src/lib/A-Command/A-Command.entity.ts +49 -8
- package/src/lib/A-Command/A-Command.error.ts +2 -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).
|
|
266
|
+
*
|
|
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
|
|
67
278
|
*
|
|
68
|
-
*
|
|
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);
|
|
80
368
|
__decorateClass([
|
|
81
|
-
aConcept.A_Feature.
|
|
82
|
-
|
|
369
|
+
aConcept.A_Feature.Extend({
|
|
370
|
+
name: "onRequest" /* onRequest */
|
|
371
|
+
})
|
|
372
|
+
], A_Channel.prototype, "onRequest", 1);
|
|
83
373
|
__decorateClass([
|
|
84
|
-
aConcept.A_Feature.
|
|
85
|
-
|
|
374
|
+
aConcept.A_Feature.Extend({
|
|
375
|
+
name: "onAfterRequest" /* onAfterRequest */
|
|
376
|
+
})
|
|
377
|
+
], A_Channel.prototype, "onAfterRequest", 1);
|
|
378
|
+
__decorateClass([
|
|
379
|
+
aConcept.A_Feature.Extend({
|
|
380
|
+
name: "onError" /* onError */
|
|
381
|
+
})
|
|
382
|
+
], A_Channel.prototype, "onError", 1);
|
|
383
|
+
__decorateClass([
|
|
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) => {
|
|
@@ -188,6 +490,9 @@ var A_Memory = class extends aConcept.A_Fragment {
|
|
|
188
490
|
return obj;
|
|
189
491
|
}
|
|
190
492
|
};
|
|
493
|
+
var A_CommandError = class extends aConcept.A_Error {
|
|
494
|
+
};
|
|
495
|
+
A_CommandError.CommandScopeBindingError = "A-Command Scope Binding Error";
|
|
191
496
|
|
|
192
497
|
// src/lib/A-Command/A-Command.entity.ts
|
|
193
498
|
var A_Command = class extends aConcept.A_Entity {
|
|
@@ -293,9 +598,7 @@ var A_Command = class extends aConcept.A_Entity {
|
|
|
293
598
|
}
|
|
294
599
|
this._status = "INITIALIZATION" /* INITIALIZATION */;
|
|
295
600
|
this._startTime = /* @__PURE__ */ new Date();
|
|
296
|
-
|
|
297
|
-
this.scope.inherit(aConcept.A_Context.scope(this));
|
|
298
|
-
}
|
|
601
|
+
this.checkScopeInheritance();
|
|
299
602
|
this.emit("init");
|
|
300
603
|
await this.call("init", this.scope);
|
|
301
604
|
this._status = "INITIALIZED" /* INITIALIZED */;
|
|
@@ -305,22 +608,34 @@ var A_Command = class extends aConcept.A_Entity {
|
|
|
305
608
|
if (this._status !== "INITIALIZED" /* INITIALIZED */) {
|
|
306
609
|
return;
|
|
307
610
|
}
|
|
611
|
+
this.checkScopeInheritance();
|
|
308
612
|
this._status = "COMPILATION" /* COMPILATION */;
|
|
309
613
|
this.emit("compile");
|
|
310
614
|
await this.call("compile", this.scope);
|
|
311
615
|
this._status = "COMPILED" /* COMPILED */;
|
|
312
616
|
}
|
|
617
|
+
/**
|
|
618
|
+
* Processes the command execution
|
|
619
|
+
*
|
|
620
|
+
* @returns
|
|
621
|
+
*/
|
|
622
|
+
async process() {
|
|
623
|
+
if (this._status !== "COMPILED" /* COMPILED */)
|
|
624
|
+
return;
|
|
625
|
+
this._status = "IN_PROGRESS" /* IN_PROGRESS */;
|
|
626
|
+
this.checkScopeInheritance();
|
|
627
|
+
this.emit("execute");
|
|
628
|
+
await this.call("execute", this.scope);
|
|
629
|
+
}
|
|
313
630
|
/**
|
|
314
631
|
* Executes the command logic.
|
|
315
632
|
*/
|
|
316
633
|
async execute() {
|
|
634
|
+
this.checkScopeInheritance();
|
|
317
635
|
try {
|
|
318
636
|
await this.init();
|
|
319
637
|
await this.compile();
|
|
320
|
-
|
|
321
|
-
this.emit("execute");
|
|
322
|
-
await this.call("execute", this.scope);
|
|
323
|
-
}
|
|
638
|
+
await this.process();
|
|
324
639
|
await this.complete();
|
|
325
640
|
} catch (error) {
|
|
326
641
|
await this.fail();
|
|
@@ -330,6 +645,7 @@ var A_Command = class extends aConcept.A_Entity {
|
|
|
330
645
|
* Marks the command as completed
|
|
331
646
|
*/
|
|
332
647
|
async complete() {
|
|
648
|
+
this.checkScopeInheritance();
|
|
333
649
|
this._status = "COMPLETED" /* COMPLETED */;
|
|
334
650
|
this._endTime = /* @__PURE__ */ new Date();
|
|
335
651
|
this._result = this.scope.resolve(A_Memory).toJSON();
|
|
@@ -340,6 +656,7 @@ var A_Command = class extends aConcept.A_Entity {
|
|
|
340
656
|
* Marks the command as failed
|
|
341
657
|
*/
|
|
342
658
|
async fail() {
|
|
659
|
+
this.checkScopeInheritance();
|
|
343
660
|
this._status = "FAILED" /* FAILED */;
|
|
344
661
|
this._endTime = /* @__PURE__ */ new Date();
|
|
345
662
|
this._errors = this.scope.resolve(A_Memory).Errors;
|
|
@@ -442,8 +759,21 @@ var A_Command = class extends aConcept.A_Entity {
|
|
|
442
759
|
errors: this.errors ? Array.from(this.errors).map((err) => err.toJSON()) : void 0
|
|
443
760
|
};
|
|
444
761
|
}
|
|
445
|
-
|
|
446
|
-
|
|
762
|
+
checkScopeInheritance() {
|
|
763
|
+
let attachedScope;
|
|
764
|
+
try {
|
|
765
|
+
attachedScope = aConcept.A_Context.scope(this);
|
|
766
|
+
} catch (error) {
|
|
767
|
+
throw new A_CommandError({
|
|
768
|
+
title: A_CommandError.CommandScopeBindingError,
|
|
769
|
+
description: `Command ${this.code} is not bound to any context scope. Ensure the command is properly registered within a context before execution.`,
|
|
770
|
+
originalError: error
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
if (!this.scope.isInheritedFrom(aConcept.A_Context.scope(this))) {
|
|
774
|
+
this.scope.inherit(aConcept.A_Context.scope(this));
|
|
775
|
+
}
|
|
776
|
+
}
|
|
447
777
|
};
|
|
448
778
|
|
|
449
779
|
// src/lib/A-Config/A-Config.constants.ts
|