expresso-macchiato 0.3.6 → 0.3.8-dev

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/dist/index.d.mts CHANGED
@@ -1,8 +1,20 @@
1
1
  import { Request, Response as Response$1, RequestHandler, Router, Express } from 'express';
2
2
  import { BaseEntity, MixedList, EntitySchema } from 'typeorm';
3
+ import { Socket, Namespace, Server as Server$1, ServerOptions } from 'socket.io';
3
4
  import http from 'http';
4
5
  import { Logger } from 'utils-logger-av';
5
6
 
7
+ type BackgroundServiceConstructor = {
8
+ name: string;
9
+ main: () => Promise<void>;
10
+ };
11
+
12
+ declare class BackgroundService {
13
+ readonly name: string;
14
+ readonly main: () => Promise<void>;
15
+ constructor(data: BackgroundServiceConstructor);
16
+ }
17
+
6
18
  type ErrorsMapping = Record<string, {
7
19
  status?: number;
8
20
  responseMessage?: string;
@@ -440,6 +452,46 @@ declare class RouterWrapper {
440
452
  createExpressRouter: () => Router;
441
453
  }
442
454
 
455
+ type ConnectedSocketClient<Metadata = any> = {
456
+ socket: Socket;
457
+ connectedAt: Date;
458
+ metadata?: Metadata;
459
+ };
460
+ type SocketConnectionNok = {
461
+ ok: false;
462
+ message: string;
463
+ };
464
+ type SocketConnectionOk<Metadata = any> = {
465
+ ok: true;
466
+ newMetadata?: Metadata;
467
+ };
468
+ type SocketConnectionMiddleware<Metadata extends Record<string, any> = any> = (self: SocketWrapper, client: Socket, commId?: string, metadata?: Metadata) => Promise<SocketConnectionOk<Metadata> | SocketConnectionNok>;
469
+ type SocketWrapperConstructor<Metadata extends Record<string, any> = any> = {
470
+ socket_namespace: string;
471
+ clientConnectionKey?: string;
472
+ connectionMiddleware?: SocketConnectionMiddleware<Metadata>;
473
+ afterClientConnect?: (self: SocketWrapper, client: Socket, metadata?: Metadata) => Promise<void>;
474
+ onClientDisconnect?: (...params: any[]) => Promise<void>;
475
+ listeners?: Record<string, (self: SocketWrapper, client: Socket, metadata: any, ...params: any[]) => Promise<void>>;
476
+ };
477
+
478
+ declare class SocketWrapper<Metadata extends Record<string, any> = any> {
479
+ protected connectedClients: Map<string, ConnectedSocketClient>;
480
+ readonly socket_namespace: string;
481
+ protected readonly data: SocketWrapperConstructor<Metadata>;
482
+ protected namespace?: Namespace;
483
+ constructor(data: SocketWrapperConstructor<Metadata>);
484
+ setupConnection: (io: Server$1) => void;
485
+ protected handleDisconnection: (client: Socket) => void;
486
+ broadcast: (eventName: string, data: any) => void;
487
+ broadcastExceptClient: (clientId: string, eventName: string, data: any) => void;
488
+ sendToClient: (clientId: string, eventName: string, data: any) => void;
489
+ sendToRoom: (room: string, eventName: string, data: any) => void;
490
+ getConnectedSockets: () => ConnectedSocketClient[];
491
+ getClientById: (clientId: string) => ConnectedSocketClient | undefined;
492
+ getClientByMetadataKey: (key: keyof Metadata, value: any) => ConnectedSocketClient | undefined;
493
+ }
494
+
443
495
  declare class Token<Payload extends Record<string, any> = DefaultTokenPayload> {
444
496
  private SECRET_KEY;
445
497
  private ExpTime;
@@ -448,7 +500,7 @@ declare class Token<Payload extends Record<string, any> = DefaultTokenPayload> {
448
500
  private keyStore;
449
501
  constructor(tokenPayload: TokenConstructor);
450
502
  private getKey;
451
- authorize: (req: Request) => Promise<Payload>;
503
+ authorize: (req: Request | string) => Promise<Payload>;
452
504
  private deriveEncryptionKey;
453
505
  generateJWE(payload: Payload): Promise<string>;
454
506
  verifyJWE(token: string): Promise<Payload>;
@@ -460,8 +512,11 @@ type StarterOptions = {
460
512
  clientPath?: string;
461
513
  swagger?: boolean;
462
514
  projectConfig: ProjectConfigs;
463
- beforeStartListening?: (app: Express, server?: http.Server) => void;
464
- socket?: boolean;
515
+ beforeStartListening?: (app: Express, httpServer?: http.Server, socketIoServerInstance?: Server$1) => void;
516
+ sockets?: {
517
+ wrappers: Array<SocketWrapper>;
518
+ options?: ServerOptions;
519
+ };
465
520
  tokenOptions?: {
466
521
  tokenInstance: Token;
467
522
  api?: TokenApiOptions;
@@ -472,12 +527,7 @@ type StarterOptions = {
472
527
  sync?: boolean;
473
528
  afterDbConnection?: () => Promise<void>;
474
529
  };
475
- };
476
- type SocketWrapperConstructor = {
477
- name: string;
478
- beforeConnection?: () => Promise<void>;
479
- onDisconnect?: (...params: any[]) => Promise<void>;
480
- listeners?: Record<string, (...params: any[]) => Promise<void>>;
530
+ backgroundServices?: Array<BackgroundService>;
481
531
  };
482
532
 
483
533
  declare class Starter {
@@ -591,14 +641,16 @@ type DynamicDbRouterOptions<T extends typeof BaseEntity> = {
591
641
  declare class MyLogger extends Logger {
592
642
  setFilePath: (filePath?: string) => void;
593
643
  fullLogOk: (service: string, message: string) => void;
594
- fullLogNok: (service: string, error: any, ...args: any[]) => void;
644
+ fullLogNok: (service: string, ...args: any[]) => void;
595
645
  }
596
646
  declare const log: MyLogger;
597
647
  declare const fullLogOk: (service: string, message: string) => void;
598
- declare const fullLogNok: (service: string, error: any, ...args: any[]) => void;
648
+ declare const fullLogNok: (service: string, ...args: any[]) => void;
599
649
  declare const apiOk: (res: any, status?: number, contentType?: string) => ExpressReturn;
600
650
  declare const apiNok: (err: any, status?: number) => ExpressReturn;
601
651
  declare const errorCatcher: (res: Response$1, err: unknown, errorsList?: ErrorsMapping, errorString?: string) => void;
652
+ declare const socketOk: <T extends Record<string, any> = any>(newMetadata?: T) => SocketConnectionOk;
653
+ declare const socketNok: (message: string) => SocketConnectionNok;
602
654
  declare const getCompiledPath: (__filename: string, __dirname: string, pathsWithoutExtension: string[]) => string[];
603
655
 
604
- export { type ApiKeySecurity, type BaseFormatContrainedParameter, type BaseOAuthSecurity, type BaseParameter, type BaseSchema, type BaseSecurity, type BasicAuthenticationSecurity, type BodyParameter, type Components, type Contact, type DefaultTokenPayload, type DynamicDbRouterOptions, type DynamicSwaggerOperation, type DynamicSwaggerOperationBody, type DynamicSwaggerPath, type DynamicSwaggerRequestBodyOperation, type ErrorsMapping, type ExpressReturn, type ExternalDocs, type FormDataParameter, type GenericFormat, type Header, type HeaderParameter, type Info, type IntegerFormat, type License, type ListOptions, type MethodPathHandling, type Methods, type NumberFormat, type OAuth2AccessCodeSecurity, type OAuth2ApplicationSecurity, type OAuth2ImplicitSecurity, type OAuth2PasswordSecurity, type OAuthScope, type Operation, type Parameter, type ParameterCollectionFormat, type ParameterType, type Path, type PathParameter, type ProjectConfigs, type QueryParameter, type Reference, type RequestBodyOperation, type Response, RouterWrapper, type RouterWrapperInterface, type Schema, type SchemaFormatConstraints, type SchemaV3, type SearchQuery, type SecureTokenConfig, type Security, type Server, type SocketWrapperConstructor, type Spec, Starter, type StarterOptions, type StringFormat, Swagger, type SwaggerMetadataInterface, type Tag, Token, type TokenApiOptions, type TokenConstructor, type XML, apiNok, apiOk, errorCatcher, fullLogNok, fullLogOk, getCompiledPath, log };
656
+ export { type ApiKeySecurity, BackgroundService, type BaseFormatContrainedParameter, type BaseOAuthSecurity, type BaseParameter, type BaseSchema, type BaseSecurity, type BasicAuthenticationSecurity, type BodyParameter, type Components, type ConnectedSocketClient, type Contact, type DefaultTokenPayload, type DynamicDbRouterOptions, type DynamicSwaggerOperation, type DynamicSwaggerOperationBody, type DynamicSwaggerPath, type DynamicSwaggerRequestBodyOperation, type ErrorsMapping, type ExpressReturn, type ExternalDocs, type FormDataParameter, type GenericFormat, type Header, type HeaderParameter, type Info, type IntegerFormat, type License, type ListOptions, type MethodPathHandling, type Methods, type NumberFormat, type OAuth2AccessCodeSecurity, type OAuth2ApplicationSecurity, type OAuth2ImplicitSecurity, type OAuth2PasswordSecurity, type OAuthScope, type Operation, type Parameter, type ParameterCollectionFormat, type ParameterType, type Path, type PathParameter, type ProjectConfigs, type QueryParameter, type Reference, type RequestBodyOperation, type Response, RouterWrapper, type RouterWrapperInterface, type Schema, type SchemaFormatConstraints, type SchemaV3, type SearchQuery, type SecureTokenConfig, type Security, type Server, type SocketConnectionMiddleware, type SocketConnectionNok, type SocketConnectionOk, SocketWrapper, type SocketWrapperConstructor, type Spec, Starter, type StarterOptions, type StringFormat, Swagger, type SwaggerMetadataInterface, type Tag, Token, type TokenApiOptions, type TokenConstructor, type XML, apiNok, apiOk, errorCatcher, fullLogNok, fullLogOk, getCompiledPath, log, socketNok, socketOk };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,20 @@
1
1
  import { Request, Response as Response$1, RequestHandler, Router, Express } from 'express';
2
2
  import { BaseEntity, MixedList, EntitySchema } from 'typeorm';
3
+ import { Socket, Namespace, Server as Server$1, ServerOptions } from 'socket.io';
3
4
  import http from 'http';
4
5
  import { Logger } from 'utils-logger-av';
5
6
 
7
+ type BackgroundServiceConstructor = {
8
+ name: string;
9
+ main: () => Promise<void>;
10
+ };
11
+
12
+ declare class BackgroundService {
13
+ readonly name: string;
14
+ readonly main: () => Promise<void>;
15
+ constructor(data: BackgroundServiceConstructor);
16
+ }
17
+
6
18
  type ErrorsMapping = Record<string, {
7
19
  status?: number;
8
20
  responseMessage?: string;
@@ -440,6 +452,46 @@ declare class RouterWrapper {
440
452
  createExpressRouter: () => Router;
441
453
  }
442
454
 
455
+ type ConnectedSocketClient<Metadata = any> = {
456
+ socket: Socket;
457
+ connectedAt: Date;
458
+ metadata?: Metadata;
459
+ };
460
+ type SocketConnectionNok = {
461
+ ok: false;
462
+ message: string;
463
+ };
464
+ type SocketConnectionOk<Metadata = any> = {
465
+ ok: true;
466
+ newMetadata?: Metadata;
467
+ };
468
+ type SocketConnectionMiddleware<Metadata extends Record<string, any> = any> = (self: SocketWrapper, client: Socket, commId?: string, metadata?: Metadata) => Promise<SocketConnectionOk<Metadata> | SocketConnectionNok>;
469
+ type SocketWrapperConstructor<Metadata extends Record<string, any> = any> = {
470
+ socket_namespace: string;
471
+ clientConnectionKey?: string;
472
+ connectionMiddleware?: SocketConnectionMiddleware<Metadata>;
473
+ afterClientConnect?: (self: SocketWrapper, client: Socket, metadata?: Metadata) => Promise<void>;
474
+ onClientDisconnect?: (...params: any[]) => Promise<void>;
475
+ listeners?: Record<string, (self: SocketWrapper, client: Socket, metadata: any, ...params: any[]) => Promise<void>>;
476
+ };
477
+
478
+ declare class SocketWrapper<Metadata extends Record<string, any> = any> {
479
+ protected connectedClients: Map<string, ConnectedSocketClient>;
480
+ readonly socket_namespace: string;
481
+ protected readonly data: SocketWrapperConstructor<Metadata>;
482
+ protected namespace?: Namespace;
483
+ constructor(data: SocketWrapperConstructor<Metadata>);
484
+ setupConnection: (io: Server$1) => void;
485
+ protected handleDisconnection: (client: Socket) => void;
486
+ broadcast: (eventName: string, data: any) => void;
487
+ broadcastExceptClient: (clientId: string, eventName: string, data: any) => void;
488
+ sendToClient: (clientId: string, eventName: string, data: any) => void;
489
+ sendToRoom: (room: string, eventName: string, data: any) => void;
490
+ getConnectedSockets: () => ConnectedSocketClient[];
491
+ getClientById: (clientId: string) => ConnectedSocketClient | undefined;
492
+ getClientByMetadataKey: (key: keyof Metadata, value: any) => ConnectedSocketClient | undefined;
493
+ }
494
+
443
495
  declare class Token<Payload extends Record<string, any> = DefaultTokenPayload> {
444
496
  private SECRET_KEY;
445
497
  private ExpTime;
@@ -448,7 +500,7 @@ declare class Token<Payload extends Record<string, any> = DefaultTokenPayload> {
448
500
  private keyStore;
449
501
  constructor(tokenPayload: TokenConstructor);
450
502
  private getKey;
451
- authorize: (req: Request) => Promise<Payload>;
503
+ authorize: (req: Request | string) => Promise<Payload>;
452
504
  private deriveEncryptionKey;
453
505
  generateJWE(payload: Payload): Promise<string>;
454
506
  verifyJWE(token: string): Promise<Payload>;
@@ -460,8 +512,11 @@ type StarterOptions = {
460
512
  clientPath?: string;
461
513
  swagger?: boolean;
462
514
  projectConfig: ProjectConfigs;
463
- beforeStartListening?: (app: Express, server?: http.Server) => void;
464
- socket?: boolean;
515
+ beforeStartListening?: (app: Express, httpServer?: http.Server, socketIoServerInstance?: Server$1) => void;
516
+ sockets?: {
517
+ wrappers: Array<SocketWrapper>;
518
+ options?: ServerOptions;
519
+ };
465
520
  tokenOptions?: {
466
521
  tokenInstance: Token;
467
522
  api?: TokenApiOptions;
@@ -472,12 +527,7 @@ type StarterOptions = {
472
527
  sync?: boolean;
473
528
  afterDbConnection?: () => Promise<void>;
474
529
  };
475
- };
476
- type SocketWrapperConstructor = {
477
- name: string;
478
- beforeConnection?: () => Promise<void>;
479
- onDisconnect?: (...params: any[]) => Promise<void>;
480
- listeners?: Record<string, (...params: any[]) => Promise<void>>;
530
+ backgroundServices?: Array<BackgroundService>;
481
531
  };
482
532
 
483
533
  declare class Starter {
@@ -591,14 +641,16 @@ type DynamicDbRouterOptions<T extends typeof BaseEntity> = {
591
641
  declare class MyLogger extends Logger {
592
642
  setFilePath: (filePath?: string) => void;
593
643
  fullLogOk: (service: string, message: string) => void;
594
- fullLogNok: (service: string, error: any, ...args: any[]) => void;
644
+ fullLogNok: (service: string, ...args: any[]) => void;
595
645
  }
596
646
  declare const log: MyLogger;
597
647
  declare const fullLogOk: (service: string, message: string) => void;
598
- declare const fullLogNok: (service: string, error: any, ...args: any[]) => void;
648
+ declare const fullLogNok: (service: string, ...args: any[]) => void;
599
649
  declare const apiOk: (res: any, status?: number, contentType?: string) => ExpressReturn;
600
650
  declare const apiNok: (err: any, status?: number) => ExpressReturn;
601
651
  declare const errorCatcher: (res: Response$1, err: unknown, errorsList?: ErrorsMapping, errorString?: string) => void;
652
+ declare const socketOk: <T extends Record<string, any> = any>(newMetadata?: T) => SocketConnectionOk;
653
+ declare const socketNok: (message: string) => SocketConnectionNok;
602
654
  declare const getCompiledPath: (__filename: string, __dirname: string, pathsWithoutExtension: string[]) => string[];
603
655
 
604
- export { type ApiKeySecurity, type BaseFormatContrainedParameter, type BaseOAuthSecurity, type BaseParameter, type BaseSchema, type BaseSecurity, type BasicAuthenticationSecurity, type BodyParameter, type Components, type Contact, type DefaultTokenPayload, type DynamicDbRouterOptions, type DynamicSwaggerOperation, type DynamicSwaggerOperationBody, type DynamicSwaggerPath, type DynamicSwaggerRequestBodyOperation, type ErrorsMapping, type ExpressReturn, type ExternalDocs, type FormDataParameter, type GenericFormat, type Header, type HeaderParameter, type Info, type IntegerFormat, type License, type ListOptions, type MethodPathHandling, type Methods, type NumberFormat, type OAuth2AccessCodeSecurity, type OAuth2ApplicationSecurity, type OAuth2ImplicitSecurity, type OAuth2PasswordSecurity, type OAuthScope, type Operation, type Parameter, type ParameterCollectionFormat, type ParameterType, type Path, type PathParameter, type ProjectConfigs, type QueryParameter, type Reference, type RequestBodyOperation, type Response, RouterWrapper, type RouterWrapperInterface, type Schema, type SchemaFormatConstraints, type SchemaV3, type SearchQuery, type SecureTokenConfig, type Security, type Server, type SocketWrapperConstructor, type Spec, Starter, type StarterOptions, type StringFormat, Swagger, type SwaggerMetadataInterface, type Tag, Token, type TokenApiOptions, type TokenConstructor, type XML, apiNok, apiOk, errorCatcher, fullLogNok, fullLogOk, getCompiledPath, log };
656
+ export { type ApiKeySecurity, BackgroundService, type BaseFormatContrainedParameter, type BaseOAuthSecurity, type BaseParameter, type BaseSchema, type BaseSecurity, type BasicAuthenticationSecurity, type BodyParameter, type Components, type ConnectedSocketClient, type Contact, type DefaultTokenPayload, type DynamicDbRouterOptions, type DynamicSwaggerOperation, type DynamicSwaggerOperationBody, type DynamicSwaggerPath, type DynamicSwaggerRequestBodyOperation, type ErrorsMapping, type ExpressReturn, type ExternalDocs, type FormDataParameter, type GenericFormat, type Header, type HeaderParameter, type Info, type IntegerFormat, type License, type ListOptions, type MethodPathHandling, type Methods, type NumberFormat, type OAuth2AccessCodeSecurity, type OAuth2ApplicationSecurity, type OAuth2ImplicitSecurity, type OAuth2PasswordSecurity, type OAuthScope, type Operation, type Parameter, type ParameterCollectionFormat, type ParameterType, type Path, type PathParameter, type ProjectConfigs, type QueryParameter, type Reference, type RequestBodyOperation, type Response, RouterWrapper, type RouterWrapperInterface, type Schema, type SchemaFormatConstraints, type SchemaV3, type SearchQuery, type SecureTokenConfig, type Security, type Server, type SocketConnectionMiddleware, type SocketConnectionNok, type SocketConnectionOk, SocketWrapper, type SocketWrapperConstructor, type Spec, Starter, type StarterOptions, type StringFormat, Swagger, type SwaggerMetadataInterface, type Tag, Token, type TokenApiOptions, type TokenConstructor, type XML, apiNok, apiOk, errorCatcher, fullLogNok, fullLogOk, getCompiledPath, log, socketNok, socketOk };
package/dist/index.js CHANGED
@@ -1,7 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/RouterWrapper.ts
2
- var _express = require('express'); var _express2 = _interopRequireDefault(_express);
3
-
4
- // src/_utils.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/_utils.ts
5
2
  var _path2 = require('path'); var _path3 = _interopRequireDefault(_path2);
6
3
  var _utilsloggerav = require('utils-logger-av');
7
4
  var MyLogger = class extends _utilsloggerav.Logger {
@@ -14,10 +11,12 @@ var MyLogger = class extends _utilsloggerav.Logger {
14
11
  this.ok(`[${service.toUpperCase()}]: ${message}`);
15
12
  this.file(`[${service.toUpperCase()}]: ${message}`);
16
13
  };
17
- this.fullLogNok = (service, error, ...args) => {
18
- const errMessage = _nullishCoalesce(_optionalChain([error, 'optionalAccess', _2 => _2.message]), () => ( error));
19
- this.nok(`[${service.toUpperCase()}]: ${errMessage}`);
20
- this.file(`[${service.toUpperCase()}]: ${errMessage}, ${args.join(",")}`, "error");
14
+ this.fullLogNok = (service, ...args) => {
15
+ let finalString = `[${service.toUpperCase()}]: `;
16
+ for (let i = 0; i < args.length; i++) if (i === args.length - 1) finalString += _nullishCoalesce(_optionalChain([args, 'access', _2 => _2[i], 'optionalAccess', _3 => _3.message]), () => ( args[i]));
17
+ else finalString += args[i] + " ";
18
+ this.nok(`[${service.toUpperCase()}]: ${finalString}`);
19
+ this.file(`[${service.toUpperCase()}]: ${finalString}`, "error");
21
20
  };
22
21
  }
23
22
  };
@@ -35,11 +34,30 @@ var errorCatcher = (res, err, errorsList, errorString) => {
35
34
  if (!error) res.status(500).send({ message: err.message });
36
35
  else res.status(_nullishCoalesce(error.status, () => ( 500))).send({ message: _nullishCoalesce(error.responseMessage, () => ( err.message)) });
37
36
  };
37
+ var socketOk = (newMetadata) => ({ ok: true, newMetadata });
38
+ var socketNok = (message) => ({ ok: false, message });
38
39
  var getCompiledPath = (__filename, __dirname, pathsWithoutExtension) => {
39
40
  const isCompiled = __filename.endsWith(".js");
40
41
  return pathsWithoutExtension.map((p) => _path3.default.join(__dirname, p + (isCompiled ? ".js" : ".ts")).replaceAll("\\", "/"));
41
42
  };
42
43
 
44
+ // src/BackgroundService.ts
45
+ var BackgroundService = class {
46
+ constructor(data) {
47
+ this.name = data.name;
48
+ this.main = async () => {
49
+ try {
50
+ await data.main();
51
+ } catch (error) {
52
+ fullLogNok("BACKGROUND-SERVICE", `${this.name.toUpperCase()}`, error);
53
+ }
54
+ };
55
+ }
56
+ };
57
+
58
+ // src/RouterWrapper.ts
59
+ var _express = require('express'); var _express2 = _interopRequireDefault(_express);
60
+
43
61
  // src/DynamicDbRouter.ts
44
62
  var _typeorm = require('typeorm');
45
63
 
@@ -50,7 +68,7 @@ var _DbConnector = class _DbConnector {
50
68
  constructor(projectConfig) {
51
69
  this.connect = async (entities, migrations, sync) => {
52
70
  try {
53
- if (!this.projectConfig.DB_DIALECT || !this.projectConfig.DB_NAME) throw new Error("[DB-CONNECTOR] Missing configs =>DB_DIALECT || DB_NAME");
71
+ if (!this.projectConfig.DB_DIALECT || !this.projectConfig.DB_NAME) throw new Error("[DB-CONNECTOR] Missing configs => DB_DIALECT || DB_NAME");
54
72
  const AppDataSource = new (0, _typeorm.DataSource)({
55
73
  type: this.projectConfig.DB_DIALECT,
56
74
  host: this.projectConfig.DB_HOST,
@@ -83,7 +101,7 @@ var _DbConnector = class _DbConnector {
83
101
  _DbConnector.DataSource = AppDataSource;
84
102
  log.magenta(`[DB-CONNECTOR] ORM CONNECTED`);
85
103
  } catch (err) {
86
- log.logError(err);
104
+ fullLogNok("DB-CONNECTOR", err);
87
105
  }
88
106
  };
89
107
  this.projectConfig = projectConfig;
@@ -223,7 +241,7 @@ _Swagger._addApiPath = (tag, basePath, options) => {
223
241
  const finalSchemas = {};
224
242
  for (const _path in options) {
225
243
  const path3 = `${basePath}${_path}`;
226
- if (_optionalChain([options, 'access', _3 => _3[_path], 'access', _4 => _4.get, 'optionalAccess', _5 => _5.tags])) options[_path].get.tags = [tag];
244
+ if (_optionalChain([options, 'access', _4 => _4[_path], 'access', _5 => _5.get, 'optionalAccess', _6 => _6.tags])) options[_path].get.tags = [tag];
227
245
  finalPaths[path3] = {
228
246
  get: options[_path].get,
229
247
  $ref: options[_path].$ref,
@@ -321,10 +339,10 @@ _Swagger.getIdParam = (pkLabel = "id") => ({ name: pkLabel, in: "path", required
321
339
  */
322
340
  _Swagger.getPaginationParams = (options) => {
323
341
  const listOptions = {
324
- page: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _6 => _6.page]), () => ( 0)),
325
- pageSize: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _7 => _7.pageSize]), () => ( 10)),
326
- order: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _8 => _8.order]), () => ( "ASC")),
327
- orderBy: _optionalChain([options, 'optionalAccess', _9 => _9.orderBy])
342
+ page: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _7 => _7.page]), () => ( 0)),
343
+ pageSize: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _8 => _8.pageSize]), () => ( 10)),
344
+ order: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _9 => _9.order]), () => ( "ASC")),
345
+ orderBy: _optionalChain([options, 'optionalAccess', _10 => _10.orderBy])
328
346
  };
329
347
  return Object.entries(listOptions).map(([key, val]) => ({ name: key, in: "query", default: val, required: false }));
330
348
  };
@@ -420,7 +438,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
420
438
  });
421
439
  res.send(entities);
422
440
  } catch (err) {
423
- errorCatcher(res, err, void 0, `[GET] ${options.basePath}/ => ${_nullishCoalesce(err.message, () => ( err))}`);
441
+ errorCatcher(res, err, void 0, `[GET] ${options.basePath}/ => ${_nullishCoalesce(err.message, () => ( err))}`);
424
442
  }
425
443
  });
426
444
  if (!avoidList.includes("GET")) options.router.get("/:id", async (req, res) => {
@@ -438,7 +456,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
438
456
  });
439
457
  res.send(singleEntity);
440
458
  } catch (err) {
441
- errorCatcher(res, err, void 0, `[GET] ${options.basePath}/:id => ${_nullishCoalesce(err.message, () => ( err))}`);
459
+ errorCatcher(res, err, void 0, `[GET] ${options.basePath}/:id => ${_nullishCoalesce(err.message, () => ( err))}`);
442
460
  }
443
461
  });
444
462
  if (!avoidList.includes("POST")) options.router.post("/", async (req, res) => {
@@ -452,7 +470,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
452
470
  const finalBody = {};
453
471
  const body = req.body;
454
472
  for (const key in body) {
455
- if (key !== options.primaryKey && (!options.bodyParameters || _optionalChain([options, 'access', _10 => _10.bodyParameters, 'access', _11 => _11.properties, 'optionalAccess', _12 => _12[key]]))) {
473
+ if (key !== options.primaryKey && (!options.bodyParameters || _optionalChain([options, 'access', _11 => _11.bodyParameters, 'access', _12 => _12.properties, 'optionalAccess', _13 => _13[key]]))) {
456
474
  finalBody[key] = body[key];
457
475
  }
458
476
  }
@@ -466,7 +484,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
466
484
  }
467
485
  res.send(result);
468
486
  } catch (err) {
469
- errorCatcher(res, err, void 0, `[POST] ${options.basePath}/ => ${_nullishCoalesce(err.message, () => ( err))}`);
487
+ errorCatcher(res, err, void 0, `[POST] ${options.basePath}/ => ${_nullishCoalesce(err.message, () => ( err))}`);
470
488
  }
471
489
  });
472
490
  if (!avoidList.includes("PUT")) options.router.put("/:id", async (req, res) => {
@@ -483,7 +501,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
483
501
  if (singleEntity === null) throw new Error("Entity not found");
484
502
  for (const key in body) {
485
503
  if (key !== options.primaryKey && key in singleEntity) {
486
- if (!options.bodyParameters || _optionalChain([options, 'access', _13 => _13.bodyParameters, 'access', _14 => _14.properties, 'optionalAccess', _15 => _15[key]])) {
504
+ if (!options.bodyParameters || _optionalChain([options, 'access', _14 => _14.bodyParameters, 'access', _15 => _15.properties, 'optionalAccess', _16 => _16[key]])) {
487
505
  singleEntity[key] = body[key];
488
506
  }
489
507
  }
@@ -498,7 +516,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
498
516
  }
499
517
  res.send(result);
500
518
  } catch (err) {
501
- errorCatcher(res, err, void 0, `[PUT] ${options.basePath}/:id => ${_nullishCoalesce(err.message, () => ( err))}`);
519
+ errorCatcher(res, err, void 0, `[PUT] ${options.basePath}/:id => ${_nullishCoalesce(err.message, () => ( err))}`);
502
520
  }
503
521
  });
504
522
  if (!avoidList.includes("DELETE")) options.router.delete("/:id", async (req, res) => {
@@ -519,7 +537,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
519
537
  }
520
538
  res.send(singleEntity);
521
539
  } catch (err) {
522
- errorCatcher(res, err, void 0, `[DELETE] ${options.basePath}/:id => ${_nullishCoalesce(err.message, () => ( err))}`);
540
+ errorCatcher(res, err, void 0, `[DELETE] ${options.basePath}/:id => ${_nullishCoalesce(err.message, () => ( err))}`);
523
541
  }
524
542
  });
525
543
  return options.router;
@@ -552,7 +570,7 @@ _DynamicDbRouter.addDbRouterSwagger = (options) => {
552
570
  }
553
571
  } catch (err) {
554
572
  if (err instanceof _typeorm.EntityMetadataNotFoundError)
555
- log.error(`[${options.entity.name}] Metadata required for db routing but not connected on the database`);
573
+ fullLogNok("DYNAMIC-DB-ROUTING", `[${options.entity.name}] Metadata required for db routing but not connected on the database`);
556
574
  }
557
575
  if (!avoidList.includes("LIST")) {
558
576
  const listOptions = { page: 0, pageSize: 10, order: "ASC", orderBy: options.primaryKey };
@@ -608,11 +626,11 @@ var RouterWrapper = class {
608
626
  const newRouter = _express.Router.call(void 0, );
609
627
  if (this.data.dbRouting) {
610
628
  const avoidOptionsForDefinedApis = [];
611
- if (_optionalChain([this, 'access', _16 => _16.data, 'access', _17 => _17.apis, 'optionalAccess', _18 => _18["/"], 'optionalAccess', _19 => _19.GET])) avoidOptionsForDefinedApis.push("LIST");
612
- if (_optionalChain([this, 'access', _20 => _20.data, 'access', _21 => _21.apis, 'optionalAccess', _22 => _22["/:id"], 'optionalAccess', _23 => _23.GET])) avoidOptionsForDefinedApis.push("GET");
613
- if (_optionalChain([this, 'access', _24 => _24.data, 'access', _25 => _25.apis, 'optionalAccess', _26 => _26["/"], 'optionalAccess', _27 => _27.POST])) avoidOptionsForDefinedApis.push("POST");
614
- if (_optionalChain([this, 'access', _28 => _28.data, 'access', _29 => _29.apis, 'optionalAccess', _30 => _30["/:id"], 'optionalAccess', _31 => _31.PUT])) avoidOptionsForDefinedApis.push("PUT");
615
- if (_optionalChain([this, 'access', _32 => _32.data, 'access', _33 => _33.apis, 'optionalAccess', _34 => _34["/:id"], 'optionalAccess', _35 => _35.DELETE])) avoidOptionsForDefinedApis.push("DELETE");
629
+ if (_optionalChain([this, 'access', _17 => _17.data, 'access', _18 => _18.apis, 'optionalAccess', _19 => _19["/"], 'optionalAccess', _20 => _20.GET])) avoidOptionsForDefinedApis.push("LIST");
630
+ if (_optionalChain([this, 'access', _21 => _21.data, 'access', _22 => _22.apis, 'optionalAccess', _23 => _23["/:id"], 'optionalAccess', _24 => _24.GET])) avoidOptionsForDefinedApis.push("GET");
631
+ if (_optionalChain([this, 'access', _25 => _25.data, 'access', _26 => _26.apis, 'optionalAccess', _27 => _27["/"], 'optionalAccess', _28 => _28.POST])) avoidOptionsForDefinedApis.push("POST");
632
+ if (_optionalChain([this, 'access', _29 => _29.data, 'access', _30 => _30.apis, 'optionalAccess', _31 => _31["/:id"], 'optionalAccess', _32 => _32.PUT])) avoidOptionsForDefinedApis.push("PUT");
633
+ if (_optionalChain([this, 'access', _33 => _33.data, 'access', _34 => _34.apis, 'optionalAccess', _35 => _35["/:id"], 'optionalAccess', _36 => _36.DELETE])) avoidOptionsForDefinedApis.push("DELETE");
616
634
  for (const avoid of _nullishCoalesce(this.data.dbRouting.avoid, () => ( []))) {
617
635
  if (!avoidOptionsForDefinedApis.includes(avoid)) avoidOptionsForDefinedApis.push(avoid);
618
636
  }
@@ -637,7 +655,7 @@ var RouterWrapper = class {
637
655
  const path3 = _path.startsWith("/") ? _path : `/${_path}`;
638
656
  if (!this.data.apis || !this.data.apis[path3]) continue;
639
657
  for (const method in this.data.apis[path3]) {
640
- if ((_nullishCoalesce(_optionalChain([this, 'access', _36 => _36.data, 'access', _37 => _37.apis, 'optionalAccess', _38 => _38[path3], 'optionalAccess', _39 => _39[method]]), () => ( void 0))) === void 0) continue;
658
+ if ((_nullishCoalesce(_optionalChain([this, 'access', _37 => _37.data, 'access', _38 => _38.apis, 'optionalAccess', _39 => _39[path3], 'optionalAccess', _40 => _40[method]]), () => ( void 0))) === void 0) continue;
641
659
  const currentMethod = this.data.apis[path3][method];
642
660
  const middlewares = _nullishCoalesce(currentMethod.middlewares, () => ( []));
643
661
  const callBackFunction = async (req, res) => {
@@ -649,8 +667,8 @@ var RouterWrapper = class {
649
667
  } else if (typeof handlerRes.result === "object") res.status(handlerRes.status).json(handlerRes.result);
650
668
  else res.status(handlerRes.status).send(handlerRes.result);
651
669
  } catch (err) {
652
- fullLogNok("api", `[${method}] ${this.data.basePath}${path3} => ${_nullishCoalesce(err.message, () => ( err))}`);
653
- res.status(500).send(_nullishCoalesce(_optionalChain([err, 'optionalAccess', _40 => _40.message]), () => ( err)));
670
+ fullLogNok("api", `[${method}] ${this.data.basePath}${path3} => ${_nullishCoalesce(err.message, () => ( err))}`);
671
+ res.status(500).send(_nullishCoalesce(_optionalChain([err, 'optionalAccess', _41 => _41.message]), () => ( err)));
654
672
  }
655
673
  };
656
674
  if (method === "GET") newRouter.get(path3, middlewares, callBackFunction);
@@ -679,7 +697,7 @@ var RouterWrapper = class {
679
697
  basePath: this.data.basePath,
680
698
  tag: this.data.tag,
681
699
  avoid: this.data.dbRouting.avoid,
682
- secure: _optionalChain([this, 'access', _41 => _41.data, 'access', _42 => _42.dbRouting, 'optionalAccess', _43 => _43.secure])
700
+ secure: _optionalChain([this, 'access', _42 => _42.data, 'access', _43 => _43.dbRouting, 'optionalAccess', _44 => _44.secure])
683
701
  });
684
702
  }
685
703
  return newRouter;
@@ -689,10 +707,112 @@ var RouterWrapper = class {
689
707
  }
690
708
  };
691
709
 
710
+ // src/SocketWrapper.ts
711
+ var SocketWrapper = class {
712
+ constructor(data) {
713
+ this.connectedClients = /* @__PURE__ */ new Map();
714
+ this.setupConnection = (io) => {
715
+ try {
716
+ if (!this.data.listeners) throw new Error("No listeners provided");
717
+ this.namespace = io.of(`/${this.socket_namespace}`);
718
+ if (this.data.connectionMiddleware) {
719
+ io.use(async (client, next) => {
720
+ const commId = client.handshake.query.commId;
721
+ const metadata = client.handshake.query.metadata;
722
+ const beforeResult = await this.data.connectionMiddleware(this, client, commId, metadata);
723
+ if (!beforeResult.ok) {
724
+ const err = new Error(beforeResult.message);
725
+ return next(err);
726
+ }
727
+ if (beforeResult.newMetadata) client.handshake.query.metadata = beforeResult.newMetadata;
728
+ next();
729
+ });
730
+ }
731
+ io.on("connection", (client) => {
732
+ try {
733
+ if (!this.namespace) throw new Error("Socket.IO not initialized");
734
+ const metadata = client.handshake.query.metadata;
735
+ const finalClientId = this.data.clientConnectionKey ? _nullishCoalesce(_optionalChain([metadata, 'optionalAccess', _45 => _45[this.data.clientConnectionKey]]), () => ( client.id)) : client.id;
736
+ this.connectedClients.set(finalClientId, { socket: client, connectedAt: /* @__PURE__ */ new Date(), metadata });
737
+ log.cyan(`[SOCKETWRAPPER] [${this.socket_namespace.toUpperCase()}] Client ${client.id} connected`);
738
+ if (this.data.afterClientConnect) this.data.afterClientConnect(this, client, metadata);
739
+ for (const eventName in this.data.listeners) client.on(eventName, (...params) => _optionalChain([this, 'access', _46 => _46.data, 'access', _47 => _47.listeners, 'optionalAccess', _48 => _48[eventName], 'call', _49 => _49(this, client, metadata, ...params)]));
740
+ client.on("disconnect", () => this.handleDisconnection(client));
741
+ } catch (err) {
742
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
743
+ }
744
+ });
745
+ } catch (err) {
746
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
747
+ }
748
+ };
749
+ this.handleDisconnection = (client) => {
750
+ try {
751
+ if (!this.namespace) throw new Error("Socket.IO not initialized");
752
+ this.connectedClients.delete(client.id);
753
+ log.cyan(`[SOCKETWRAPPER] [${this.socket_namespace.toUpperCase()}] Client ${client.id} disconnected`);
754
+ if (this.data.onClientDisconnect) this.data.onClientDisconnect(client);
755
+ } catch (err) {
756
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
757
+ }
758
+ };
759
+ // --- SEND METHODS
760
+ this.broadcast = (eventName, data) => {
761
+ try {
762
+ if (!this.namespace) throw new Error("Socket.IO not initialized");
763
+ this.namespace.emit(eventName, data);
764
+ } catch (err) {
765
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
766
+ }
767
+ };
768
+ this.broadcastExceptClient = (clientId, eventName, data) => {
769
+ try {
770
+ for (const [id, client] of this.connectedClients.entries()) {
771
+ if (id !== clientId) client.socket.emit(eventName, data);
772
+ }
773
+ } catch (err) {
774
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
775
+ }
776
+ };
777
+ this.sendToClient = (clientId, eventName, data) => {
778
+ try {
779
+ const connectedClient = this.connectedClients.get(clientId);
780
+ if (!connectedClient) throw new Error(`Client ${clientId} not found`);
781
+ connectedClient.socket.emit(eventName, data);
782
+ } catch (err) {
783
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
784
+ }
785
+ };
786
+ this.sendToRoom = (room, eventName, data) => {
787
+ try {
788
+ if (!this.namespace) throw new Error("Socket.IO not initialized");
789
+ this.namespace.to(room).emit(eventName, data);
790
+ } catch (err) {
791
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
792
+ }
793
+ };
794
+ // --- GETTERS
795
+ this.getConnectedSockets = () => Array.from(this.connectedClients.values());
796
+ this.getClientById = (clientId) => this.connectedClients.get(clientId);
797
+ this.getClientByMetadataKey = (key, value) => {
798
+ for (const client of this.connectedClients.values()) {
799
+ if (client.metadata && client.metadata[key] === value) return client;
800
+ }
801
+ return void 0;
802
+ };
803
+ this.socket_namespace = data.socket_namespace;
804
+ this.data = data;
805
+ Object.keys(_nullishCoalesce(data.listeners, () => ( {}))).forEach((key) => {
806
+ this[key] = _optionalChain([data, 'access', _50 => _50.listeners, 'optionalAccess', _51 => _51[key], 'access', _52 => _52.bind, 'call', _53 => _53(this)]);
807
+ });
808
+ }
809
+ };
810
+
692
811
  // src/Starter.ts
693
812
 
694
813
  var _http = require('http'); var _http2 = _interopRequireDefault(_http);
695
814
 
815
+ var _socketio = require('socket.io');
696
816
  var _swaggeruiexpress = require('swagger-ui-express'); var _swaggeruiexpress2 = _interopRequireDefault(_swaggeruiexpress);
697
817
  var Starter = class {
698
818
  constructor(options) {
@@ -721,19 +841,22 @@ var Starter = class {
721
841
  const clientPath = _path3.default.resolve(process.cwd(), "client");
722
842
  app.use(_express2.default.static(clientPath));
723
843
  app.get("/apiUrl", (_, res) => res.send(options.projectConfig.API_URL));
724
- if (_optionalChain([options, 'access', _44 => _44.tokenOptions, 'optionalAccess', _45 => _45.api])) {
844
+ if (_optionalChain([options, 'access', _54 => _54.tokenOptions, 'optionalAccess', _55 => _55.api])) {
725
845
  app.get(_nullishCoalesce(options.tokenOptions.api.path, () => ( "/api/auth")), options.tokenOptions.api.callback);
726
846
  }
727
847
  app.get("*", (_, res) => {
728
848
  res.sendFile(_path3.default.join(clientPath, "index.html"));
729
849
  });
730
850
  }
731
- if (options.socket === void 0 || options.socket === false) {
851
+ for (const service of _nullishCoalesce(options.backgroundServices, () => ( []))) service.main();
852
+ if (options.sockets === void 0) {
732
853
  if (options.beforeStartListening) options.beforeStartListening(app);
733
854
  app.listen(options.projectConfig.SERVER_PORT, () => log.base("Server started.", `Listening on port ${options.projectConfig.SERVER_PORT}`));
734
- } else if (options.socket === true) {
855
+ } else {
735
856
  const server = _http2.default.createServer(app);
736
- if (options.beforeStartListening) options.beforeStartListening(app, server);
857
+ const socketIoServerInstance = new (0, _socketio.Server)(server, options.sockets.options);
858
+ for (const socket of options.sockets.wrappers) socket.setupConnection(socketIoServerInstance);
859
+ if (options.beforeStartListening) options.beforeStartListening(app, server, socketIoServerInstance);
737
860
  server.listen(options.projectConfig.SERVER_PORT, () => log.base("Server started.", `Listening on port ${options.projectConfig.SERVER_PORT}`));
738
861
  }
739
862
  };
@@ -745,7 +868,7 @@ var Starter = class {
745
868
  log.setFilePath(options.projectConfig.ERROR_FILE_PATH);
746
869
  this.init(options);
747
870
  } catch (err) {
748
- log.error(err);
871
+ fullLogNok("starter", err);
749
872
  }
750
873
  }
751
874
  };
@@ -758,7 +881,11 @@ var Token = class {
758
881
  this.keyStore = null;
759
882
  // Metodo per autorizzare una richiesta
760
883
  this.authorize = async (req) => {
761
- const token = _nullishCoalesce(_optionalChain([req, 'access', _46 => _46.headers, 'access', _47 => _47.authorization, 'optionalAccess', _48 => _48.split, 'call', _49 => _49("Bearer "), 'optionalAccess', _50 => _50[1]]), () => ( null));
884
+ if (typeof req === "string") {
885
+ const payload2 = await this.verifyJWE(req);
886
+ return payload2;
887
+ }
888
+ const token = _nullishCoalesce(_optionalChain([req, 'access', _56 => _56.headers, 'access', _57 => _57.authorization, 'optionalAccess', _58 => _58.split, 'call', _59 => _59("Bearer "), 'optionalAccess', _60 => _60[1]]), () => ( null));
762
889
  if (token === null) throw new Error("UNAUTH");
763
890
  const payload = await this.verifyJWE(token);
764
891
  return payload;
@@ -828,4 +955,8 @@ var Token = class {
828
955
 
829
956
 
830
957
 
831
- exports.RouterWrapper = RouterWrapper; exports.Starter = Starter; exports.Swagger = Swagger; exports.Token = Token; exports.apiNok = apiNok; exports.apiOk = apiOk; exports.errorCatcher = errorCatcher; exports.fullLogNok = fullLogNok; exports.fullLogOk = fullLogOk; exports.getCompiledPath = getCompiledPath; exports.log = log;
958
+
959
+
960
+
961
+
962
+ exports.BackgroundService = BackgroundService; exports.RouterWrapper = RouterWrapper; exports.SocketWrapper = SocketWrapper; exports.Starter = Starter; exports.Swagger = Swagger; exports.Token = Token; exports.apiNok = apiNok; exports.apiOk = apiOk; exports.errorCatcher = errorCatcher; exports.fullLogNok = fullLogNok; exports.fullLogOk = fullLogOk; exports.getCompiledPath = getCompiledPath; exports.log = log; exports.socketNok = socketNok; exports.socketOk = socketOk;
package/dist/index.mjs CHANGED
@@ -1,6 +1,3 @@
1
- // src/RouterWrapper.ts
2
- import { Router } from "express";
3
-
4
1
  // src/_utils.ts
5
2
  import path from "path";
6
3
  import { Logger } from "utils-logger-av";
@@ -14,10 +11,12 @@ var MyLogger = class extends Logger {
14
11
  this.ok(`[${service.toUpperCase()}]: ${message}`);
15
12
  this.file(`[${service.toUpperCase()}]: ${message}`);
16
13
  };
17
- this.fullLogNok = (service, error, ...args) => {
18
- const errMessage = error?.message ?? error;
19
- this.nok(`[${service.toUpperCase()}]: ${errMessage}`);
20
- this.file(`[${service.toUpperCase()}]: ${errMessage}, ${args.join(",")}`, "error");
14
+ this.fullLogNok = (service, ...args) => {
15
+ let finalString = `[${service.toUpperCase()}]: `;
16
+ for (let i = 0; i < args.length; i++) if (i === args.length - 1) finalString += args[i]?.message ?? args[i];
17
+ else finalString += args[i] + " ";
18
+ this.nok(`[${service.toUpperCase()}]: ${finalString}`);
19
+ this.file(`[${service.toUpperCase()}]: ${finalString}`, "error");
21
20
  };
22
21
  }
23
22
  };
@@ -35,11 +34,30 @@ var errorCatcher = (res, err, errorsList, errorString) => {
35
34
  if (!error) res.status(500).send({ message: err.message });
36
35
  else res.status(error.status ?? 500).send({ message: error.responseMessage ?? err.message });
37
36
  };
37
+ var socketOk = (newMetadata) => ({ ok: true, newMetadata });
38
+ var socketNok = (message) => ({ ok: false, message });
38
39
  var getCompiledPath = (__filename2, __dirname2, pathsWithoutExtension) => {
39
40
  const isCompiled = __filename2.endsWith(".js");
40
41
  return pathsWithoutExtension.map((p) => path.join(__dirname2, p + (isCompiled ? ".js" : ".ts")).replaceAll("\\", "/"));
41
42
  };
42
43
 
44
+ // src/BackgroundService.ts
45
+ var BackgroundService = class {
46
+ constructor(data) {
47
+ this.name = data.name;
48
+ this.main = async () => {
49
+ try {
50
+ await data.main();
51
+ } catch (error) {
52
+ fullLogNok("BACKGROUND-SERVICE", `${this.name.toUpperCase()}`, error);
53
+ }
54
+ };
55
+ }
56
+ };
57
+
58
+ // src/RouterWrapper.ts
59
+ import { Router } from "express";
60
+
43
61
  // src/DynamicDbRouter.ts
44
62
  import { EntityMetadataNotFoundError, Equal, Like } from "typeorm";
45
63
 
@@ -50,7 +68,7 @@ var _DbConnector = class _DbConnector {
50
68
  constructor(projectConfig) {
51
69
  this.connect = async (entities, migrations, sync) => {
52
70
  try {
53
- if (!this.projectConfig.DB_DIALECT || !this.projectConfig.DB_NAME) throw new Error("[DB-CONNECTOR] Missing configs =>DB_DIALECT || DB_NAME");
71
+ if (!this.projectConfig.DB_DIALECT || !this.projectConfig.DB_NAME) throw new Error("[DB-CONNECTOR] Missing configs => DB_DIALECT || DB_NAME");
54
72
  const AppDataSource = new DataSource({
55
73
  type: this.projectConfig.DB_DIALECT,
56
74
  host: this.projectConfig.DB_HOST,
@@ -83,7 +101,7 @@ var _DbConnector = class _DbConnector {
83
101
  _DbConnector.DataSource = AppDataSource;
84
102
  log.magenta(`[DB-CONNECTOR] ORM CONNECTED`);
85
103
  } catch (err) {
86
- log.logError(err);
104
+ fullLogNok("DB-CONNECTOR", err);
87
105
  }
88
106
  };
89
107
  this.projectConfig = projectConfig;
@@ -420,7 +438,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
420
438
  });
421
439
  res.send(entities);
422
440
  } catch (err) {
423
- errorCatcher(res, err, void 0, `[GET] ${options.basePath}/ => ${err.message ?? err}`);
441
+ errorCatcher(res, err, void 0, `[GET] ${options.basePath}/ => ${err.message ?? err}`);
424
442
  }
425
443
  });
426
444
  if (!avoidList.includes("GET")) options.router.get("/:id", async (req, res) => {
@@ -438,7 +456,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
438
456
  });
439
457
  res.send(singleEntity);
440
458
  } catch (err) {
441
- errorCatcher(res, err, void 0, `[GET] ${options.basePath}/:id => ${err.message ?? err}`);
459
+ errorCatcher(res, err, void 0, `[GET] ${options.basePath}/:id => ${err.message ?? err}`);
442
460
  }
443
461
  });
444
462
  if (!avoidList.includes("POST")) options.router.post("/", async (req, res) => {
@@ -466,7 +484,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
466
484
  }
467
485
  res.send(result);
468
486
  } catch (err) {
469
- errorCatcher(res, err, void 0, `[POST] ${options.basePath}/ => ${err.message ?? err}`);
487
+ errorCatcher(res, err, void 0, `[POST] ${options.basePath}/ => ${err.message ?? err}`);
470
488
  }
471
489
  });
472
490
  if (!avoidList.includes("PUT")) options.router.put("/:id", async (req, res) => {
@@ -498,7 +516,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
498
516
  }
499
517
  res.send(result);
500
518
  } catch (err) {
501
- errorCatcher(res, err, void 0, `[PUT] ${options.basePath}/:id => ${err.message ?? err}`);
519
+ errorCatcher(res, err, void 0, `[PUT] ${options.basePath}/:id => ${err.message ?? err}`);
502
520
  }
503
521
  });
504
522
  if (!avoidList.includes("DELETE")) options.router.delete("/:id", async (req, res) => {
@@ -519,7 +537,7 @@ _DynamicDbRouter.createDbRouter = (options) => {
519
537
  }
520
538
  res.send(singleEntity);
521
539
  } catch (err) {
522
- errorCatcher(res, err, void 0, `[DELETE] ${options.basePath}/:id => ${err.message ?? err}`);
540
+ errorCatcher(res, err, void 0, `[DELETE] ${options.basePath}/:id => ${err.message ?? err}`);
523
541
  }
524
542
  });
525
543
  return options.router;
@@ -552,7 +570,7 @@ _DynamicDbRouter.addDbRouterSwagger = (options) => {
552
570
  }
553
571
  } catch (err) {
554
572
  if (err instanceof EntityMetadataNotFoundError)
555
- log.error(`[${options.entity.name}] Metadata required for db routing but not connected on the database`);
573
+ fullLogNok("DYNAMIC-DB-ROUTING", `[${options.entity.name}] Metadata required for db routing but not connected on the database`);
556
574
  }
557
575
  if (!avoidList.includes("LIST")) {
558
576
  const listOptions = { page: 0, pageSize: 10, order: "ASC", orderBy: options.primaryKey };
@@ -649,7 +667,7 @@ var RouterWrapper = class {
649
667
  } else if (typeof handlerRes.result === "object") res.status(handlerRes.status).json(handlerRes.result);
650
668
  else res.status(handlerRes.status).send(handlerRes.result);
651
669
  } catch (err) {
652
- fullLogNok("api", `[${method}] ${this.data.basePath}${path3} => ${err.message ?? err}`);
670
+ fullLogNok("api", `[${method}] ${this.data.basePath}${path3} => ${err.message ?? err}`);
653
671
  res.status(500).send(err?.message ?? err);
654
672
  }
655
673
  };
@@ -689,10 +707,112 @@ var RouterWrapper = class {
689
707
  }
690
708
  };
691
709
 
710
+ // src/SocketWrapper.ts
711
+ var SocketWrapper = class {
712
+ constructor(data) {
713
+ this.connectedClients = /* @__PURE__ */ new Map();
714
+ this.setupConnection = (io) => {
715
+ try {
716
+ if (!this.data.listeners) throw new Error("No listeners provided");
717
+ this.namespace = io.of(`/${this.socket_namespace}`);
718
+ if (this.data.connectionMiddleware) {
719
+ io.use(async (client, next) => {
720
+ const commId = client.handshake.query.commId;
721
+ const metadata = client.handshake.query.metadata;
722
+ const beforeResult = await this.data.connectionMiddleware(this, client, commId, metadata);
723
+ if (!beforeResult.ok) {
724
+ const err = new Error(beforeResult.message);
725
+ return next(err);
726
+ }
727
+ if (beforeResult.newMetadata) client.handshake.query.metadata = beforeResult.newMetadata;
728
+ next();
729
+ });
730
+ }
731
+ io.on("connection", (client) => {
732
+ try {
733
+ if (!this.namespace) throw new Error("Socket.IO not initialized");
734
+ const metadata = client.handshake.query.metadata;
735
+ const finalClientId = this.data.clientConnectionKey ? metadata?.[this.data.clientConnectionKey] ?? client.id : client.id;
736
+ this.connectedClients.set(finalClientId, { socket: client, connectedAt: /* @__PURE__ */ new Date(), metadata });
737
+ log.cyan(`[SOCKETWRAPPER] [${this.socket_namespace.toUpperCase()}] Client ${client.id} connected`);
738
+ if (this.data.afterClientConnect) this.data.afterClientConnect(this, client, metadata);
739
+ for (const eventName in this.data.listeners) client.on(eventName, (...params) => this.data.listeners?.[eventName](this, client, metadata, ...params));
740
+ client.on("disconnect", () => this.handleDisconnection(client));
741
+ } catch (err) {
742
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
743
+ }
744
+ });
745
+ } catch (err) {
746
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
747
+ }
748
+ };
749
+ this.handleDisconnection = (client) => {
750
+ try {
751
+ if (!this.namespace) throw new Error("Socket.IO not initialized");
752
+ this.connectedClients.delete(client.id);
753
+ log.cyan(`[SOCKETWRAPPER] [${this.socket_namespace.toUpperCase()}] Client ${client.id} disconnected`);
754
+ if (this.data.onClientDisconnect) this.data.onClientDisconnect(client);
755
+ } catch (err) {
756
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
757
+ }
758
+ };
759
+ // --- SEND METHODS
760
+ this.broadcast = (eventName, data) => {
761
+ try {
762
+ if (!this.namespace) throw new Error("Socket.IO not initialized");
763
+ this.namespace.emit(eventName, data);
764
+ } catch (err) {
765
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
766
+ }
767
+ };
768
+ this.broadcastExceptClient = (clientId, eventName, data) => {
769
+ try {
770
+ for (const [id, client] of this.connectedClients.entries()) {
771
+ if (id !== clientId) client.socket.emit(eventName, data);
772
+ }
773
+ } catch (err) {
774
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
775
+ }
776
+ };
777
+ this.sendToClient = (clientId, eventName, data) => {
778
+ try {
779
+ const connectedClient = this.connectedClients.get(clientId);
780
+ if (!connectedClient) throw new Error(`Client ${clientId} not found`);
781
+ connectedClient.socket.emit(eventName, data);
782
+ } catch (err) {
783
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
784
+ }
785
+ };
786
+ this.sendToRoom = (room, eventName, data) => {
787
+ try {
788
+ if (!this.namespace) throw new Error("Socket.IO not initialized");
789
+ this.namespace.to(room).emit(eventName, data);
790
+ } catch (err) {
791
+ fullLogNok(`SOCKETWRAPPER`, `[${this.socket_namespace.toUpperCase()}]`, err);
792
+ }
793
+ };
794
+ // --- GETTERS
795
+ this.getConnectedSockets = () => Array.from(this.connectedClients.values());
796
+ this.getClientById = (clientId) => this.connectedClients.get(clientId);
797
+ this.getClientByMetadataKey = (key, value) => {
798
+ for (const client of this.connectedClients.values()) {
799
+ if (client.metadata && client.metadata[key] === value) return client;
800
+ }
801
+ return void 0;
802
+ };
803
+ this.socket_namespace = data.socket_namespace;
804
+ this.data = data;
805
+ Object.keys(data.listeners ?? {}).forEach((key) => {
806
+ this[key] = data.listeners?.[key].bind(this);
807
+ });
808
+ }
809
+ };
810
+
692
811
  // src/Starter.ts
693
812
  import express from "express";
694
813
  import http from "http";
695
814
  import path2 from "path";
815
+ import { Server } from "socket.io";
696
816
  import swaggerUi from "swagger-ui-express";
697
817
  var Starter = class {
698
818
  constructor(options) {
@@ -728,12 +848,15 @@ var Starter = class {
728
848
  res.sendFile(path2.join(clientPath, "index.html"));
729
849
  });
730
850
  }
731
- if (options.socket === void 0 || options.socket === false) {
851
+ for (const service of options.backgroundServices ?? []) service.main();
852
+ if (options.sockets === void 0) {
732
853
  if (options.beforeStartListening) options.beforeStartListening(app);
733
854
  app.listen(options.projectConfig.SERVER_PORT, () => log.base("Server started.", `Listening on port ${options.projectConfig.SERVER_PORT}`));
734
- } else if (options.socket === true) {
855
+ } else {
735
856
  const server = http.createServer(app);
736
- if (options.beforeStartListening) options.beforeStartListening(app, server);
857
+ const socketIoServerInstance = new Server(server, options.sockets.options);
858
+ for (const socket of options.sockets.wrappers) socket.setupConnection(socketIoServerInstance);
859
+ if (options.beforeStartListening) options.beforeStartListening(app, server, socketIoServerInstance);
737
860
  server.listen(options.projectConfig.SERVER_PORT, () => log.base("Server started.", `Listening on port ${options.projectConfig.SERVER_PORT}`));
738
861
  }
739
862
  };
@@ -745,7 +868,7 @@ var Starter = class {
745
868
  log.setFilePath(options.projectConfig.ERROR_FILE_PATH);
746
869
  this.init(options);
747
870
  } catch (err) {
748
- log.error(err);
871
+ fullLogNok("starter", err);
749
872
  }
750
873
  }
751
874
  };
@@ -758,6 +881,10 @@ var Token = class {
758
881
  this.keyStore = null;
759
882
  // Metodo per autorizzare una richiesta
760
883
  this.authorize = async (req) => {
884
+ if (typeof req === "string") {
885
+ const payload2 = await this.verifyJWE(req);
886
+ return payload2;
887
+ }
761
888
  const token = req.headers.authorization?.split("Bearer ")?.[1] ?? null;
762
889
  if (token === null) throw new Error("UNAUTH");
763
890
  const payload = await this.verifyJWE(token);
@@ -817,7 +944,9 @@ var Token = class {
817
944
  }
818
945
  };
819
946
  export {
947
+ BackgroundService,
820
948
  RouterWrapper,
949
+ SocketWrapper,
821
950
  Starter,
822
951
  Swagger,
823
952
  Token,
@@ -827,5 +956,7 @@ export {
827
956
  fullLogNok,
828
957
  fullLogOk,
829
958
  getCompiledPath,
830
- log
959
+ log,
960
+ socketNok,
961
+ socketOk
831
962
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expresso-macchiato",
3
- "version": "0.3.6",
3
+ "version": "0.3.8-dev",
4
4
  "author": "Alessio Velluso",
5
5
  "license": "MIT",
6
6
  "description": "Description",
@@ -33,11 +33,12 @@
33
33
  "dotenv": "^16.3.1",
34
34
  "express": "^4.18.2",
35
35
  "jsonwebtoken": "^9.0.2",
36
- "swagger-jsdoc": "^6.2.8",
37
- "swagger-ui-express": "^5.0.1",
38
36
  "multer": "^1.4.5-lts.1",
39
37
  "node-jose": "^2.2.0",
40
38
  "reflect-metadata": "^0.2.2",
39
+ "socket.io": "^4.8.1",
40
+ "swagger-jsdoc": "^6.2.8",
41
+ "swagger-ui-express": "^5.0.1",
41
42
  "utils-logger-av": "^4.0.0",
42
43
  "utils-stuff": "^4.5.0"
43
44
  },
@@ -0,0 +1,4 @@
1
+ export type BackgroundServiceConstructor = {
2
+ name:string;
3
+ main: () => Promise<void>
4
+ }
@@ -0,0 +1,23 @@
1
+ import { Socket } from "socket.io";
2
+ import { SocketWrapper } from "../src";
3
+
4
+ export type ConnectedSocketClient<Metadata = any> = {
5
+ socket: Socket;
6
+ connectedAt: Date;
7
+ metadata?: Metadata;
8
+ }
9
+
10
+ export type SocketConnectionNok = { ok:false, message:string }
11
+ export type SocketConnectionOk<Metadata = any> = { ok:true, newMetadata?: Metadata }
12
+
13
+
14
+ export type SocketConnectionMiddleware<Metadata extends Record<string, any> = any> = (self:SocketWrapper, client:Socket, commId?:string, metadata?:Metadata) => Promise<SocketConnectionOk<Metadata> | SocketConnectionNok>
15
+ export type SocketWrapperConstructor<Metadata extends Record<string, any> = any> =
16
+ {
17
+ socketNamespace:string,
18
+ clientConnectionKey?:string,
19
+ connectionMiddleware?:SocketConnectionMiddleware<Metadata>
20
+ afterClientConnect?: (self:SocketWrapper, client:Socket, metadata?:Metadata) => Promise<void>
21
+ onClientDisconnect?:(...params:any[]) => Promise<void>
22
+ listeners?:Record<string, (self:SocketWrapper, client:Socket, metadata:any, ...params:any[]) => Promise<void>>
23
+ }
@@ -1,7 +1,10 @@
1
1
  import { Express } from "express"
2
2
  import http from "http"
3
+ import { Server, ServerOptions } from "socket.io"
3
4
  import { EntitySchema, MixedList } from "typeorm"
5
+ import { BackgroundService } from "../src/BackgroundService"
4
6
  import { RouterWrapper } from "../src/RouterWrapper"
7
+ import { SocketWrapper } from "../src/SocketWrapper"
5
8
  import { Token } from "../src/Token"
6
9
  import { ProjectConfigs } from "./generic.sptypes"
7
10
  import { TokenApiOptions } from "./token.sptypes"
@@ -12,8 +15,11 @@ export type StarterOptions = {
12
15
  clientPath?:string,
13
16
  swagger?:boolean,
14
17
  projectConfig:ProjectConfigs,
15
- beforeStartListening?:(app:Express, server?:http.Server) => void,
16
- socket?:boolean,
18
+ beforeStartListening?:(app:Express, httpServer?:http.Server, socketIoServerInstance?:Server) => void,
19
+ sockets?: {
20
+ wrappers:Array<SocketWrapper>,
21
+ options?:ServerOptions
22
+ },
17
23
  tokenOptions?: {
18
24
  tokenInstance: Token,
19
25
  api?:TokenApiOptions
@@ -24,13 +30,5 @@ export type StarterOptions = {
24
30
  sync?:boolean,
25
31
  afterDbConnection?:() => Promise<void>
26
32
  },
27
- }
28
-
29
-
30
-
31
- export type SocketWrapperConstructor = {
32
- name:string,
33
- beforeConnection?:() => Promise<void>
34
- onDisconnect?:(...params:any[]) => Promise<void>
35
- listeners?:Record<string, (...params:any[]) => Promise<void>>
33
+ backgroundServices?:Array<BackgroundService>
36
34
  }