@adaas/a-server 0.0.23 → 0.0.25

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 (49) hide show
  1. package/dist/browser/index.d.mts +30 -0
  2. package/dist/browser/index.mjs +68 -2
  3. package/dist/browser/index.mjs.map +1 -1
  4. package/dist/node/{A-Response.entity-BVYAc6-8.d.mts → A-Response.entity-6qhiV7BE.d.mts} +30 -0
  5. package/dist/node/{A-Response.entity-CRc-t-vr.d.ts → A-Response.entity-bjh6bofZ.d.ts} +30 -0
  6. package/dist/node/controllers/A-CommandController/A-CommandController.component.d.mts +1 -1
  7. package/dist/node/controllers/A-CommandController/A-CommandController.component.d.ts +1 -1
  8. package/dist/node/controllers/A-EntityController/A-EntityController.component.d.mts +1 -1
  9. package/dist/node/controllers/A-EntityController/A-EntityController.component.d.ts +1 -1
  10. package/dist/node/controllers/A-ListingController/A-ListingController.component.d.mts +1 -1
  11. package/dist/node/controllers/A-ListingController/A-ListingController.component.d.ts +1 -1
  12. package/dist/node/controllers/A-ServerHealthMonitor/A-ServerHealthMonitor.component.d.mts +1 -1
  13. package/dist/node/controllers/A-ServerHealthMonitor/A-ServerHealthMonitor.component.d.ts +1 -1
  14. package/dist/node/controllers/A-ServerHealthMonitor/A-ServerHealthMonitor.component.js +11 -2
  15. package/dist/node/controllers/A-ServerHealthMonitor/A-ServerHealthMonitor.component.js.map +1 -1
  16. package/dist/node/controllers/A-ServerHealthMonitor/A-ServerHealthMonitor.component.mjs +7 -3
  17. package/dist/node/controllers/A-ServerHealthMonitor/A-ServerHealthMonitor.component.mjs.map +1 -1
  18. package/dist/node/index.d.mts +1 -1
  19. package/dist/node/index.d.ts +1 -1
  20. package/dist/node/lib/A-Response/A-Response.entity.d.mts +1 -1
  21. package/dist/node/lib/A-Response/A-Response.entity.d.ts +1 -1
  22. package/dist/node/lib/A-Response/A-Response.entity.js +65 -1
  23. package/dist/node/lib/A-Response/A-Response.entity.js.map +1 -1
  24. package/dist/node/lib/A-Response/A-Response.entity.mjs +65 -1
  25. package/dist/node/lib/A-Response/A-Response.entity.mjs.map +1 -1
  26. package/dist/node/lib/A-Response/A-Response.types.d.mts +1 -1
  27. package/dist/node/lib/A-Response/A-Response.types.d.ts +1 -1
  28. package/dist/node/lib/A-Server/A-HttpServer.container.d.mts +1 -1
  29. package/dist/node/lib/A-Server/A-HttpServer.container.d.ts +1 -1
  30. package/dist/node/lib/A-Server/A-HttpServer.container.js +3 -1
  31. package/dist/node/lib/A-Server/A-HttpServer.container.js.map +1 -1
  32. package/dist/node/lib/A-Server/A-HttpServer.container.mjs +3 -1
  33. package/dist/node/lib/A-Server/A-HttpServer.container.mjs.map +1 -1
  34. package/dist/node/lib/A-ServerController/A-ServerController.component.d.mts +1 -1
  35. package/dist/node/lib/A-ServerController/A-ServerController.component.d.ts +1 -1
  36. package/dist/node/lib/A-ServerLogger/A-ServerLogger.component.d.mts +1 -1
  37. package/dist/node/lib/A-ServerLogger/A-ServerLogger.component.d.ts +1 -1
  38. package/dist/node/lib/A-ServerProxy/A-ServerProxy.component.d.mts +1 -1
  39. package/dist/node/lib/A-ServerProxy/A-ServerProxy.component.d.ts +1 -1
  40. package/dist/node/lib/A-ServerRouter/A-ServerRouter.component.d.mts +1 -1
  41. package/dist/node/lib/A-ServerRouter/A-ServerRouter.component.d.ts +1 -1
  42. package/dist/node/lib/A-ServerStatic/A-ServerStatic.component.d.mts +1 -1
  43. package/dist/node/lib/A-ServerStatic/A-ServerStatic.component.d.ts +1 -1
  44. package/dist/node/middlewares/A-ServerCORS/A_ServerCORS.component.d.mts +1 -1
  45. package/dist/node/middlewares/A-ServerCORS/A_ServerCORS.component.d.ts +1 -1
  46. package/package.json +8 -4
  47. package/src/controllers/A-ServerHealthMonitor/A-ServerHealthMonitor.component.ts +7 -4
  48. package/src/lib/A-Response/A-Response.entity.ts +63 -1
  49. package/src/lib/A-Server/A-HttpServer.container.ts +6 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaas/a-server",
3
- "version": "0.0.23",
3
+ "version": "0.0.25",
4
4
  "description": "A-Server is a powerful server framework designed to work seamlessly with the A-Concept framework. This library provides a robust and flexible server implementation of A-Server, enabling developers to create scalable and efficient server-side applications using the A-Concept architecture.",
5
5
  "keywords": [
6
6
  "adaas",
@@ -289,11 +289,15 @@
289
289
  "echo-version": "echo $npm_package_version",
290
290
  "build": "tsup --config tsup.config.ts"
291
291
  },
292
- "dependencies": {
293
- "@adaas/a-concept": "^0.3.15",
294
- "@adaas/a-utils": "^0.3.19"
292
+ "peerDependencies": {
293
+ "@adaas/a-concept": "^0.3.16",
294
+ "@adaas/a-frame": "^0.1.2",
295
+ "@adaas/a-utils": "^0.3.20"
295
296
  },
296
297
  "devDependencies": {
298
+ "@adaas/a-concept": "^0.3.15",
299
+ "@adaas/a-frame": "^0.1.2",
300
+ "@adaas/a-utils": "^0.3.19",
297
301
  "@types/chai": "^4.3.14",
298
302
  "@types/jest": "^29.5.12",
299
303
  "@types/mocha": "^10.0.6",
@@ -1,9 +1,11 @@
1
- import { A_Component, A_Inject } from "@adaas/a-concept";
1
+ import { A_Component, A_CONCEPT_ENV, A_Inject } from "@adaas/a-concept";
2
2
  import { A_ServerRouter } from "@adaas/a-server/router/A-ServerRouter.component";
3
3
  import { A_Request } from "@adaas/a-server/request/A-Request.entity";
4
4
  import { A_Response } from "@adaas/a-server/response/A-Response.entity";
5
5
  import { A_Config } from "@adaas/a-utils/a-config";
6
6
  import { A_ServerLogger } from "@adaas/a-server/logger/A-ServerLogger.component";
7
+ import fs from "fs";
8
+ import path from "path";
7
9
 
8
10
 
9
11
 
@@ -25,8 +27,9 @@ export class A_ServerHealthMonitor extends A_Component {
25
27
  @A_Inject(A_Response) response: A_Response,
26
28
  @A_Inject(A_ServerLogger) logger: A_ServerLogger
27
29
  ): Promise<any> {
28
- const packageJSON = await import(`${config.get('A_CONCEPT_ROOT_FOLDER')}/package.json`,
29
- { with: { type: 'json' } });
30
+ const rootFolder = config.get('A_CONCEPT_ROOT_FOLDER') || A_CONCEPT_ENV.A_CONCEPT_ROOT_FOLDER || process.cwd();
31
+ const pkgPath = path.join(rootFolder, 'package.json');
32
+ const packageJSON = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
30
33
 
31
34
 
32
35
  const exposedProperties: Array<string> = config.get('EXPOSED_PROPERTIES')?.split(',') || [
@@ -35,6 +38,6 @@ export class A_ServerHealthMonitor extends A_Component {
35
38
  'description',
36
39
  ];
37
40
 
38
- exposedProperties.forEach(prop => response.add(prop, packageJSON.default[prop]));
41
+ exposedProperties.forEach(prop => response.add(prop, packageJSON[prop]));
39
42
  }
40
43
  }
@@ -89,6 +89,10 @@ export class A_Response<_ResponseType = any> extends A_Entity<
89
89
  * Event listeners map for A_Response events
90
90
  */
91
91
  private _listeners: Map<A_ResponseFeatureNames, Set<A_Response_Listener>> = new Map();
92
+ /**
93
+ * Whether this response is operating as a persistent SSE stream
94
+ */
95
+ private _isStreaming: boolean = false;
92
96
 
93
97
 
94
98
  constructor(params: A_Response_Constructor, options?: A_Response_Options) {
@@ -158,6 +162,14 @@ export class A_Response<_ResponseType = any> extends A_Entity<
158
162
  get size(): number {
159
163
  return this.original.getHeader('Content-Length') as number || 0;
160
164
  }
165
+ /**
166
+ * Whether this response is in SSE streaming mode.
167
+ * When true the server container will NOT auto-send and destroy() will
168
+ * leave the underlying socket open.
169
+ */
170
+ get isStreaming(): boolean {
171
+ return this._isStreaming;
172
+ }
161
173
 
162
174
  // ======================================================================================
163
175
  // --------------------------------------------------------------------------
@@ -188,7 +200,7 @@ export class A_Response<_ResponseType = any> extends A_Entity<
188
200
  */
189
201
  async destroy(): Promise<any> {
190
202
 
191
- if (!this.original.destroyed) {
203
+ if (!this.original.destroyed && !this._isStreaming) {
192
204
  this.original.end();
193
205
  this._listeners.clear();
194
206
  this.original.removeAllListeners();
@@ -312,6 +324,56 @@ export class A_Response<_ResponseType = any> extends A_Entity<
312
324
  }));
313
325
  }
314
326
  }
327
+ // ======================================================================================
328
+ // --------------------------------------------------------------------------
329
+ // A-Response SSE (Server-Sent Events) Methods
330
+ // --------------------------------------------------------------------------
331
+ // ======================================================================================
332
+ /**
333
+ * Upgrade this response to a persistent SSE stream.
334
+ * Sends the required headers and writes the initial `:ok` comment to flush
335
+ * the connection. After calling this the response will NOT be auto-closed
336
+ * by the server container or by destroy().
337
+ */
338
+ public sseOpen(): void {
339
+ if (this.headersSent || this._isStreaming) return;
340
+ this._isStreaming = true;
341
+ this.original.writeHead(200, {
342
+ 'Content-Type': 'text/event-stream',
343
+ 'Cache-Control': 'no-cache, no-transform',
344
+ 'Connection': 'keep-alive',
345
+ 'X-Accel-Buffering': 'no',
346
+ });
347
+ this.original.write(':ok\n\n');
348
+ // Reset streaming flag when the client disconnects
349
+ this.original.once('close', () => {
350
+ this._isStreaming = false;
351
+ });
352
+ }
353
+ /**
354
+ * Write a named SSE event onto the open stream.
355
+ * Format: `event: <name>\ndata: <JSON>\n\n`
356
+ *
357
+ * Compatible with browser EventSource `addEventListener(name, handler)`.
358
+ *
359
+ * @returns false when the channel is no longer writable
360
+ */
361
+ public sseWrite(event: string, data?: any): boolean {
362
+ if (!this._isStreaming || this.original.destroyed) return false;
363
+ try {
364
+ return this.original.write(`event: ${event}\ndata: ${JSON.stringify(data ?? {})}\n\n`);
365
+ } catch {
366
+ return false;
367
+ }
368
+ }
369
+ /**
370
+ * Close the SSE stream gracefully.
371
+ */
372
+ public sseClose(): void {
373
+ if (!this._isStreaming || this.original.destroyed) return;
374
+ this._isStreaming = false;
375
+ this.original.end();
376
+ }
315
377
  /**
316
378
  * Write head with status and headers
317
379
  */
@@ -197,7 +197,12 @@ export class A_HttpServer extends A_Service {
197
197
 
198
198
 
199
199
  req.clearTimeout();
200
- await res.status(200).send();
200
+
201
+ // For SSE streams the controller calls response.sseOpen() which keeps
202
+ // the socket alive; skip the auto-send so we don't close it here.
203
+ if (!res.isStreaming) {
204
+ await res.status(200).send();
205
+ }
201
206
 
202
207
  resolve();
203
208
  } catch (error) {