diff --git a/.config/sonar-project.properties b/.config/sonar-project.properties
index d25882d6..1e98678e 100644
--- a/.config/sonar-project.properties
+++ b/.config/sonar-project.properties
@@ -1,244 +1,254 @@
sonar.projectKey=Mytra-Development-Framework-NDF-TypeScript
sonar.projectName=Mytra Development Framework - NDF - TypeScript
-sonar.modules=api-core,api-crash,api-doorkeeper,api-firehose,api-logger,api-middlewares,api-openc2-core,api-utils,components-app-wrapper,components-observability,components-openc2,providers-amqp,providers-elastic,providers-http-client,providers-http-server,providers-kafka,providers-mongo,providers-redis,providers-service-setup,providers-socket-client,providers-socket-server,registries-error,registries-health,registries-metrics
+sonar.modules=registries-metrics,registries-health,registries-error,providers-socket-server,providers-socket-client,providers-service-setup,providers-redis,providers-mongo,providers-kafka,providers-http-server,providers-http-client,providers-elastic,providers-amqp,components-openc2,components-observability,components-app-wrapper,api-utils,api-openc2-core,api-middlewares,api-logger,api-firehose,api-faker,api-doorkeeper,api-crash,api-core
sonar.exclusions=coveragereport/**/*,packages/**/*.test.ts,packages/**/test/*.ts,packages/**/*.js
-api-core.sonar.projectName=NDS-API-CORE-Typescript
-api-core.sonar.projectBaseDir=packages/api/core
-api-core.sonar.sources=src
-api-core.sonar.inclusions=src/**/*
-api-core.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-api-core.sonar.test.inclusions=src/**/*.test.ts
-api-core.sonar.javascript.lcov.reportPaths=../../../coverage/api/core/lcov.info
-api-core.sonar.junit.reportPaths=../../../coverage/api/core/test-results.xml
-api-core.sonar.typescript.tsconfigPath=tsconfig.build.json
+registries-metrics.sonar.projectName=NDS-REGISTRIES-METRICS-Typescript
+registries-metrics.sonar.projectBaseDir=packages/registries/metrics
+registries-metrics.sonar.sources=src
+registries-metrics.sonar.inclusions=src/**/*
+registries-metrics.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+registries-metrics.sonar.test.inclusions=src/**/*.test.ts
+registries-metrics.sonar.javascript.lcov.reportPaths=../../../coverage/registries/metrics/lcov.info
+registries-metrics.sonar.junit.reportPaths=../../../coverage/registries/metrics/test-results.xml
+registries-metrics.sonar.typescript.tsconfigPath=tsconfig.build.json
-api-crash.sonar.projectName=NDS-API-CRASH-Typescript
-api-crash.sonar.projectBaseDir=packages/api/crash
-api-crash.sonar.sources=src
-api-crash.sonar.inclusions=src/**/*
-api-crash.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-api-crash.sonar.test.inclusions=src/**/*.test.ts
-api-crash.sonar.javascript.lcov.reportPaths=../../../coverage/api/crash/lcov.info
-api-crash.sonar.junit.reportPaths=../../../coverage/api/crash/test-results.xml
-api-crash.sonar.typescript.tsconfigPath=tsconfig.build.json
+registries-health.sonar.projectName=NDS-REGISTRIES-HEALTH-Typescript
+registries-health.sonar.projectBaseDir=packages/registries/health
+registries-health.sonar.sources=src
+registries-health.sonar.inclusions=src/**/*
+registries-health.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+registries-health.sonar.test.inclusions=src/**/*.test.ts
+registries-health.sonar.javascript.lcov.reportPaths=../../../coverage/registries/health/lcov.info
+registries-health.sonar.junit.reportPaths=../../../coverage/registries/health/test-results.xml
+registries-health.sonar.typescript.tsconfigPath=tsconfig.build.json
-api-doorkeeper.sonar.projectName=NDS-API-DOORKEEPER-Typescript
-api-doorkeeper.sonar.projectBaseDir=packages/api/doorkeeper
-api-doorkeeper.sonar.sources=src
-api-doorkeeper.sonar.inclusions=src/**/*
-api-doorkeeper.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-api-doorkeeper.sonar.test.inclusions=src/**/*.test.ts
-api-doorkeeper.sonar.javascript.lcov.reportPaths=../../../coverage/api/doorkeeper/lcov.info
-api-doorkeeper.sonar.junit.reportPaths=../../../coverage/api/doorkeeper/test-results.xml
-api-doorkeeper.sonar.typescript.tsconfigPath=tsconfig.build.json
+registries-error.sonar.projectName=NDS-REGISTRIES-ERROR-Typescript
+registries-error.sonar.projectBaseDir=packages/registries/error
+registries-error.sonar.sources=src
+registries-error.sonar.inclusions=src/**/*
+registries-error.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+registries-error.sonar.test.inclusions=src/**/*.test.ts
+registries-error.sonar.javascript.lcov.reportPaths=../../../coverage/registries/error/lcov.info
+registries-error.sonar.junit.reportPaths=../../../coverage/registries/error/test-results.xml
+registries-error.sonar.typescript.tsconfigPath=tsconfig.build.json
-api-firehose.sonar.projectName=NDS-API-FIREHOSE-Typescript
-api-firehose.sonar.projectBaseDir=packages/api/firehose
-api-firehose.sonar.sources=src
-api-firehose.sonar.inclusions=src/**/*
-api-firehose.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-api-firehose.sonar.test.inclusions=src/**/*.test.ts
-api-firehose.sonar.javascript.lcov.reportPaths=../../../coverage/api/firehose/lcov.info
-api-firehose.sonar.junit.reportPaths=../../../coverage/api/firehose/test-results.xml
-api-firehose.sonar.typescript.tsconfigPath=tsconfig.build.json
+providers-socket-server.sonar.projectName=NDS-PROVIDERS-SOCKET-SERVER-Typescript
+providers-socket-server.sonar.projectBaseDir=packages/providers/socket-server
+providers-socket-server.sonar.sources=src
+providers-socket-server.sonar.inclusions=src/**/*
+providers-socket-server.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+providers-socket-server.sonar.test.inclusions=src/**/*.test.ts
+providers-socket-server.sonar.javascript.lcov.reportPaths=../../../coverage/providers/socket-server/lcov.info
+providers-socket-server.sonar.junit.reportPaths=../../../coverage/providers/socket-server/test-results.xml
+providers-socket-server.sonar.typescript.tsconfigPath=tsconfig.build.json
-api-logger.sonar.projectName=NDS-API-LOGGER-Typescript
-api-logger.sonar.projectBaseDir=packages/api/logger
-api-logger.sonar.sources=src
-api-logger.sonar.inclusions=src/**/*
-api-logger.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-api-logger.sonar.test.inclusions=src/**/*.test.ts
-api-logger.sonar.javascript.lcov.reportPaths=../../../coverage/api/logger/lcov.info
-api-logger.sonar.junit.reportPaths=../../../coverage/api/logger/test-results.xml
-api-logger.sonar.typescript.tsconfigPath=tsconfig.build.json
+providers-socket-client.sonar.projectName=NDS-PROVIDERS-SOCKET-CLIENT-Typescript
+providers-socket-client.sonar.projectBaseDir=packages/providers/socket-client
+providers-socket-client.sonar.sources=src
+providers-socket-client.sonar.inclusions=src/**/*
+providers-socket-client.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+providers-socket-client.sonar.test.inclusions=src/**/*.test.ts
+providers-socket-client.sonar.javascript.lcov.reportPaths=../../../coverage/providers/socket-client/lcov.info
+providers-socket-client.sonar.junit.reportPaths=../../../coverage/providers/socket-client/test-results.xml
+providers-socket-client.sonar.typescript.tsconfigPath=tsconfig.build.json
-api-middlewares.sonar.projectName=NDS-API-MIDDLEWARES-Typescript
-api-middlewares.sonar.projectBaseDir=packages/api/middlewares
-api-middlewares.sonar.sources=src
-api-middlewares.sonar.inclusions=src/**/*
-api-middlewares.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-api-middlewares.sonar.test.inclusions=src/**/*.test.ts
-api-middlewares.sonar.javascript.lcov.reportPaths=../../../coverage/api/middlewares/lcov.info
-api-middlewares.sonar.junit.reportPaths=../../../coverage/api/middlewares/test-results.xml
-api-middlewares.sonar.typescript.tsconfigPath=tsconfig.build.json
+providers-service-setup.sonar.projectName=NDS-PROVIDERS-SERVICE-SETUP-Typescript
+providers-service-setup.sonar.projectBaseDir=packages/providers/service-setup
+providers-service-setup.sonar.sources=src
+providers-service-setup.sonar.inclusions=src/**/*
+providers-service-setup.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+providers-service-setup.sonar.test.inclusions=src/**/*.test.ts
+providers-service-setup.sonar.javascript.lcov.reportPaths=../../../coverage/providers/service-setup/lcov.info
+providers-service-setup.sonar.junit.reportPaths=../../../coverage/providers/service-setup/test-results.xml
+providers-service-setup.sonar.typescript.tsconfigPath=tsconfig.build.json
-api-openc2-core.sonar.projectName=NDS-API-OPENC2-CORE-Typescript
-api-openc2-core.sonar.projectBaseDir=packages/api/openc2-core
-api-openc2-core.sonar.sources=src
-api-openc2-core.sonar.inclusions=src/**/*
-api-openc2-core.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-api-openc2-core.sonar.test.inclusions=src/**/*.test.ts
-api-openc2-core.sonar.javascript.lcov.reportPaths=../../../coverage/api/openc2-core/lcov.info
-api-openc2-core.sonar.junit.reportPaths=../../../coverage/api/openc2-core/test-results.xml
-api-openc2-core.sonar.typescript.tsconfigPath=tsconfig.build.json
+providers-redis.sonar.projectName=NDS-PROVIDERS-REDIS-Typescript
+providers-redis.sonar.projectBaseDir=packages/providers/redis
+providers-redis.sonar.sources=src
+providers-redis.sonar.inclusions=src/**/*
+providers-redis.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+providers-redis.sonar.test.inclusions=src/**/*.test.ts
+providers-redis.sonar.javascript.lcov.reportPaths=../../../coverage/providers/redis/lcov.info
+providers-redis.sonar.junit.reportPaths=../../../coverage/providers/redis/test-results.xml
+providers-redis.sonar.typescript.tsconfigPath=tsconfig.build.json
-api-utils.sonar.projectName=NDS-API-UTILS-Typescript
-api-utils.sonar.projectBaseDir=packages/api/utils
-api-utils.sonar.sources=src
-api-utils.sonar.inclusions=src/**/*
-api-utils.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-api-utils.sonar.test.inclusions=src/**/*.test.ts
-api-utils.sonar.javascript.lcov.reportPaths=../../../coverage/api/utils/lcov.info
-api-utils.sonar.junit.reportPaths=../../../coverage/api/utils/test-results.xml
-api-utils.sonar.typescript.tsconfigPath=tsconfig.build.json
+providers-mongo.sonar.projectName=NDS-PROVIDERS-MONGO-Typescript
+providers-mongo.sonar.projectBaseDir=packages/providers/mongo
+providers-mongo.sonar.sources=src
+providers-mongo.sonar.inclusions=src/**/*
+providers-mongo.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+providers-mongo.sonar.test.inclusions=src/**/*.test.ts
+providers-mongo.sonar.javascript.lcov.reportPaths=../../../coverage/providers/mongo/lcov.info
+providers-mongo.sonar.junit.reportPaths=../../../coverage/providers/mongo/test-results.xml
+providers-mongo.sonar.typescript.tsconfigPath=tsconfig.build.json
-components-app-wrapper.sonar.projectName=NDS-COMPONENTS-APP-WRAPPER-Typescript
-components-app-wrapper.sonar.projectBaseDir=packages/components/app-wrapper
-components-app-wrapper.sonar.sources=src
-components-app-wrapper.sonar.inclusions=src/**/*
-components-app-wrapper.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-components-app-wrapper.sonar.test.inclusions=src/**/*.test.ts
-components-app-wrapper.sonar.javascript.lcov.reportPaths=../../../coverage/components/app-wrapper/lcov.info
-components-app-wrapper.sonar.junit.reportPaths=../../../coverage/components/app-wrapper/test-results.xml
-components-app-wrapper.sonar.typescript.tsconfigPath=tsconfig.build.json
+providers-kafka.sonar.projectName=NDS-PROVIDERS-KAFKA-Typescript
+providers-kafka.sonar.projectBaseDir=packages/providers/kafka
+providers-kafka.sonar.sources=src
+providers-kafka.sonar.inclusions=src/**/*
+providers-kafka.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+providers-kafka.sonar.test.inclusions=src/**/*.test.ts
+providers-kafka.sonar.javascript.lcov.reportPaths=../../../coverage/providers/kafka/lcov.info
+providers-kafka.sonar.junit.reportPaths=../../../coverage/providers/kafka/test-results.xml
+providers-kafka.sonar.typescript.tsconfigPath=tsconfig.build.json
-components-observability.sonar.projectName=NDS-COMPONENTS-OBSERVABILITY-Typescript
-components-observability.sonar.projectBaseDir=packages/components/observability
-components-observability.sonar.sources=src
-components-observability.sonar.inclusions=src/**/*
-components-observability.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-components-observability.sonar.test.inclusions=src/**/*.test.ts
-components-observability.sonar.javascript.lcov.reportPaths=../../../coverage/components/observability/lcov.info
-components-observability.sonar.junit.reportPaths=../../../coverage/components/observability/test-results.xml
-components-observability.sonar.typescript.tsconfigPath=tsconfig.build.json
+providers-http-server.sonar.projectName=NDS-PROVIDERS-HTTP-SERVER-Typescript
+providers-http-server.sonar.projectBaseDir=packages/providers/http-server
+providers-http-server.sonar.sources=src
+providers-http-server.sonar.inclusions=src/**/*
+providers-http-server.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+providers-http-server.sonar.test.inclusions=src/**/*.test.ts
+providers-http-server.sonar.javascript.lcov.reportPaths=../../../coverage/providers/http-server/lcov.info
+providers-http-server.sonar.junit.reportPaths=../../../coverage/providers/http-server/test-results.xml
+providers-http-server.sonar.typescript.tsconfigPath=tsconfig.build.json
-components-openc2.sonar.projectName=NDS-COMPONENTS-OPENC2-Typescript
-components-openc2.sonar.projectBaseDir=packages/components/openc2
-components-openc2.sonar.sources=src
-components-openc2.sonar.inclusions=src/**/*
-components-openc2.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-components-openc2.sonar.test.inclusions=src/**/*.test.ts
-components-openc2.sonar.javascript.lcov.reportPaths=../../../coverage/components/openc2/lcov.info
-components-openc2.sonar.junit.reportPaths=../../../coverage/components/openc2/test-results.xml
-components-openc2.sonar.typescript.tsconfigPath=tsconfig.build.json
+providers-http-client.sonar.projectName=NDS-PROVIDERS-HTTP-CLIENT-Typescript
+providers-http-client.sonar.projectBaseDir=packages/providers/http-client
+providers-http-client.sonar.sources=src
+providers-http-client.sonar.inclusions=src/**/*
+providers-http-client.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+providers-http-client.sonar.test.inclusions=src/**/*.test.ts
+providers-http-client.sonar.javascript.lcov.reportPaths=../../../coverage/providers/http-client/lcov.info
+providers-http-client.sonar.junit.reportPaths=../../../coverage/providers/http-client/test-results.xml
+providers-http-client.sonar.typescript.tsconfigPath=tsconfig.build.json
+
+providers-elastic.sonar.projectName=NDS-PROVIDERS-ELASTIC-Typescript
+providers-elastic.sonar.projectBaseDir=packages/providers/elastic
+providers-elastic.sonar.sources=src
+providers-elastic.sonar.inclusions=src/**/*
+providers-elastic.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+providers-elastic.sonar.test.inclusions=src/**/*.test.ts
+providers-elastic.sonar.javascript.lcov.reportPaths=../../../coverage/providers/elastic/lcov.info
+providers-elastic.sonar.junit.reportPaths=../../../coverage/providers/elastic/test-results.xml
+providers-elastic.sonar.typescript.tsconfigPath=tsconfig.build.json
providers-amqp.sonar.projectName=NDS-PROVIDERS-AMQP-Typescript
providers-amqp.sonar.projectBaseDir=packages/providers/amqp
providers-amqp.sonar.sources=src
providers-amqp.sonar.inclusions=src/**/*
-providers-amqp.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
+providers-amqp.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
providers-amqp.sonar.test.inclusions=src/**/*.test.ts
providers-amqp.sonar.javascript.lcov.reportPaths=../../../coverage/providers/amqp/lcov.info
providers-amqp.sonar.junit.reportPaths=../../../coverage/providers/amqp/test-results.xml
providers-amqp.sonar.typescript.tsconfigPath=tsconfig.build.json
-providers-elastic.sonar.projectName=NDS-PROVIDERS-ELASTIC-Typescript
-providers-elastic.sonar.projectBaseDir=packages/providers/elastic
-providers-elastic.sonar.sources=src
-providers-elastic.sonar.inclusions=src/**/*
-providers-elastic.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-providers-elastic.sonar.test.inclusions=src/**/*.test.ts
-providers-elastic.sonar.javascript.lcov.reportPaths=../../../coverage/providers/elastic/lcov.info
-providers-elastic.sonar.junit.reportPaths=../../../coverage/providers/elastic/test-results.xml
-providers-elastic.sonar.typescript.tsconfigPath=tsconfig.build.json
+components-openc2.sonar.projectName=NDS-COMPONENTS-OPENC2-Typescript
+components-openc2.sonar.projectBaseDir=packages/components/openc2
+components-openc2.sonar.sources=src
+components-openc2.sonar.inclusions=src/**/*
+components-openc2.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+components-openc2.sonar.test.inclusions=src/**/*.test.ts
+components-openc2.sonar.javascript.lcov.reportPaths=../../../coverage/components/openc2/lcov.info
+components-openc2.sonar.junit.reportPaths=../../../coverage/components/openc2/test-results.xml
+components-openc2.sonar.typescript.tsconfigPath=tsconfig.build.json
-providers-http-client.sonar.projectName=NDS-PROVIDERS-HTTP-CLIENT-Typescript
-providers-http-client.sonar.projectBaseDir=packages/providers/http-client
-providers-http-client.sonar.sources=src
-providers-http-client.sonar.inclusions=src/**/*
-providers-http-client.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-providers-http-client.sonar.test.inclusions=src/**/*.test.ts
-providers-http-client.sonar.javascript.lcov.reportPaths=../../../coverage/providers/http-client/lcov.info
-providers-http-client.sonar.junit.reportPaths=../../../coverage/providers/http-client/test-results.xml
-providers-http-client.sonar.typescript.tsconfigPath=tsconfig.build.json
+components-observability.sonar.projectName=NDS-COMPONENTS-OBSERVABILITY-Typescript
+components-observability.sonar.projectBaseDir=packages/components/observability
+components-observability.sonar.sources=src
+components-observability.sonar.inclusions=src/**/*
+components-observability.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+components-observability.sonar.test.inclusions=src/**/*.test.ts
+components-observability.sonar.javascript.lcov.reportPaths=../../../coverage/components/observability/lcov.info
+components-observability.sonar.junit.reportPaths=../../../coverage/components/observability/test-results.xml
+components-observability.sonar.typescript.tsconfigPath=tsconfig.build.json
-providers-http-server.sonar.projectName=NDS-PROVIDERS-HTTP-SERVER-Typescript
-providers-http-server.sonar.projectBaseDir=packages/providers/http-server
-providers-http-server.sonar.sources=src
-providers-http-server.sonar.inclusions=src/**/*
-providers-http-server.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-providers-http-server.sonar.test.inclusions=src/**/*.test.ts
-providers-http-server.sonar.javascript.lcov.reportPaths=../../../coverage/providers/http-server/lcov.info
-providers-http-server.sonar.junit.reportPaths=../../../coverage/providers/http-server/test-results.xml
-providers-http-server.sonar.typescript.tsconfigPath=tsconfig.build.json
+components-app-wrapper.sonar.projectName=NDS-COMPONENTS-APP-WRAPPER-Typescript
+components-app-wrapper.sonar.projectBaseDir=packages/components/app-wrapper
+components-app-wrapper.sonar.sources=src
+components-app-wrapper.sonar.inclusions=src/**/*
+components-app-wrapper.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+components-app-wrapper.sonar.test.inclusions=src/**/*.test.ts
+components-app-wrapper.sonar.javascript.lcov.reportPaths=../../../coverage/components/app-wrapper/lcov.info
+components-app-wrapper.sonar.junit.reportPaths=../../../coverage/components/app-wrapper/test-results.xml
+components-app-wrapper.sonar.typescript.tsconfigPath=tsconfig.build.json
-providers-kafka.sonar.projectName=NDS-PROVIDERS-KAFKA-Typescript
-providers-kafka.sonar.projectBaseDir=packages/providers/kafka
-providers-kafka.sonar.sources=src
-providers-kafka.sonar.inclusions=src/**/*
-providers-kafka.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-providers-kafka.sonar.test.inclusions=src/**/*.test.ts
-providers-kafka.sonar.javascript.lcov.reportPaths=../../../coverage/providers/kafka/lcov.info
-providers-kafka.sonar.junit.reportPaths=../../../coverage/providers/kafka/test-results.xml
-providers-kafka.sonar.typescript.tsconfigPath=tsconfig.build.json
+api-utils.sonar.projectName=NDS-API-UTILS-Typescript
+api-utils.sonar.projectBaseDir=packages/api/utils
+api-utils.sonar.sources=src
+api-utils.sonar.inclusions=src/**/*
+api-utils.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+api-utils.sonar.test.inclusions=src/**/*.test.ts
+api-utils.sonar.javascript.lcov.reportPaths=../../../coverage/api/utils/lcov.info
+api-utils.sonar.junit.reportPaths=../../../coverage/api/utils/test-results.xml
+api-utils.sonar.typescript.tsconfigPath=tsconfig.build.json
-providers-mongo.sonar.projectName=NDS-PROVIDERS-MONGO-Typescript
-providers-mongo.sonar.projectBaseDir=packages/providers/mongo
-providers-mongo.sonar.sources=src
-providers-mongo.sonar.inclusions=src/**/*
-providers-mongo.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-providers-mongo.sonar.test.inclusions=src/**/*.test.ts
-providers-mongo.sonar.javascript.lcov.reportPaths=../../../coverage/providers/mongo/lcov.info
-providers-mongo.sonar.junit.reportPaths=../../../coverage/providers/mongo/test-results.xml
-providers-mongo.sonar.typescript.tsconfigPath=tsconfig.build.json
+api-openc2-core.sonar.projectName=NDS-API-OPENC2-CORE-Typescript
+api-openc2-core.sonar.projectBaseDir=packages/api/openc2-core
+api-openc2-core.sonar.sources=src
+api-openc2-core.sonar.inclusions=src/**/*
+api-openc2-core.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+api-openc2-core.sonar.test.inclusions=src/**/*.test.ts
+api-openc2-core.sonar.javascript.lcov.reportPaths=../../../coverage/api/openc2-core/lcov.info
+api-openc2-core.sonar.junit.reportPaths=../../../coverage/api/openc2-core/test-results.xml
+api-openc2-core.sonar.typescript.tsconfigPath=tsconfig.build.json
-providers-redis.sonar.projectName=NDS-PROVIDERS-REDIS-Typescript
-providers-redis.sonar.projectBaseDir=packages/providers/redis
-providers-redis.sonar.sources=src
-providers-redis.sonar.inclusions=src/**/*
-providers-redis.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-providers-redis.sonar.test.inclusions=src/**/*.test.ts
-providers-redis.sonar.javascript.lcov.reportPaths=../../../coverage/providers/redis/lcov.info
-providers-redis.sonar.junit.reportPaths=../../../coverage/providers/redis/test-results.xml
-providers-redis.sonar.typescript.tsconfigPath=tsconfig.build.json
+api-middlewares.sonar.projectName=NDS-API-MIDDLEWARES-Typescript
+api-middlewares.sonar.projectBaseDir=packages/api/middlewares
+api-middlewares.sonar.sources=src
+api-middlewares.sonar.inclusions=src/**/*
+api-middlewares.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+api-middlewares.sonar.test.inclusions=src/**/*.test.ts
+api-middlewares.sonar.javascript.lcov.reportPaths=../../../coverage/api/middlewares/lcov.info
+api-middlewares.sonar.junit.reportPaths=../../../coverage/api/middlewares/test-results.xml
+api-middlewares.sonar.typescript.tsconfigPath=tsconfig.build.json
-providers-service-setup.sonar.projectName=NDS-PROVIDERS-SERVICE-SETUP-Typescript
-providers-service-setup.sonar.projectBaseDir=packages/providers/service-setup
-providers-service-setup.sonar.sources=src
-providers-service-setup.sonar.inclusions=src/**/*
-providers-service-setup.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-providers-service-setup.sonar.test.inclusions=src/**/*.test.ts
-providers-service-setup.sonar.javascript.lcov.reportPaths=../../../coverage/providers/service-setup/lcov.info
-providers-service-setup.sonar.junit.reportPaths=../../../coverage/providers/service-setup/test-results.xml
-providers-service-setup.sonar.typescript.tsconfigPath=tsconfig.build.json
+api-logger.sonar.projectName=NDS-API-LOGGER-Typescript
+api-logger.sonar.projectBaseDir=packages/api/logger
+api-logger.sonar.sources=src
+api-logger.sonar.inclusions=src/**/*
+api-logger.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+api-logger.sonar.test.inclusions=src/**/*.test.ts
+api-logger.sonar.javascript.lcov.reportPaths=../../../coverage/api/logger/lcov.info
+api-logger.sonar.junit.reportPaths=../../../coverage/api/logger/test-results.xml
+api-logger.sonar.typescript.tsconfigPath=tsconfig.build.json
-providers-socket-client.sonar.projectName=NDS-PROVIDERS-SOCKET-CLIENT-Typescript
-providers-socket-client.sonar.projectBaseDir=packages/providers/socket-client
-providers-socket-client.sonar.sources=src
-providers-socket-client.sonar.inclusions=src/**/*
-providers-socket-client.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-providers-socket-client.sonar.test.inclusions=src/**/*.test.ts
-providers-socket-client.sonar.javascript.lcov.reportPaths=../../../coverage/providers/socket-client/lcov.info
-providers-socket-client.sonar.junit.reportPaths=../../../coverage/providers/socket-client/test-results.xml
-providers-socket-client.sonar.typescript.tsconfigPath=tsconfig.build.json
+api-firehose.sonar.projectName=NDS-API-FIREHOSE-Typescript
+api-firehose.sonar.projectBaseDir=packages/api/firehose
+api-firehose.sonar.sources=src
+api-firehose.sonar.inclusions=src/**/*
+api-firehose.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+api-firehose.sonar.test.inclusions=src/**/*.test.ts
+api-firehose.sonar.javascript.lcov.reportPaths=../../../coverage/api/firehose/lcov.info
+api-firehose.sonar.junit.reportPaths=../../../coverage/api/firehose/test-results.xml
+api-firehose.sonar.typescript.tsconfigPath=tsconfig.build.json
-providers-socket-server.sonar.projectName=NDS-PROVIDERS-SOCKET-SERVER-Typescript
-providers-socket-server.sonar.projectBaseDir=packages/providers/socket-server
-providers-socket-server.sonar.sources=src
-providers-socket-server.sonar.inclusions=src/**/*
-providers-socket-server.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-providers-socket-server.sonar.test.inclusions=src/**/*.test.ts
-providers-socket-server.sonar.javascript.lcov.reportPaths=../../../coverage/providers/socket-server/lcov.info
-providers-socket-server.sonar.junit.reportPaths=../../../coverage/providers/socket-server/test-results.xml
-providers-socket-server.sonar.typescript.tsconfigPath=tsconfig.build.json
+api-faker.sonar.projectName=NDS-API-FAKER-Typescript
+api-faker.sonar.projectBaseDir=packages/api/faker
+api-faker.sonar.sources=src
+api-faker.sonar.inclusions=src/**/*
+api-faker.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+api-faker.sonar.test.inclusions=src/**/*.test.ts
+api-faker.sonar.javascript.lcov.reportPaths=../../../coverage/api/faker/lcov.info
+api-faker.sonar.junit.reportPaths=../../../coverage/api/faker/test-results.xml
+api-faker.sonar.typescript.tsconfigPath=tsconfig.build.json
-registries-error.sonar.projectName=NDS-REGISTRIES-ERROR-Typescript
-registries-error.sonar.projectBaseDir=packages/registries/error
-registries-error.sonar.sources=src
-registries-error.sonar.inclusions=src/**/*
-registries-error.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-registries-error.sonar.test.inclusions=src/**/*.test.ts
-registries-error.sonar.javascript.lcov.reportPaths=../../../coverage/registries/error/lcov.info
-registries-error.sonar.junit.reportPaths=../../../coverage/registries/error/test-results.xml
-registries-error.sonar.typescript.tsconfigPath=tsconfig.build.json
+api-doorkeeper.sonar.projectName=NDS-API-DOORKEEPER-Typescript
+api-doorkeeper.sonar.projectBaseDir=packages/api/doorkeeper
+api-doorkeeper.sonar.sources=src
+api-doorkeeper.sonar.inclusions=src/**/*
+api-doorkeeper.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+api-doorkeeper.sonar.test.inclusions=src/**/*.test.ts
+api-doorkeeper.sonar.javascript.lcov.reportPaths=../../../coverage/api/doorkeeper/lcov.info
+api-doorkeeper.sonar.junit.reportPaths=../../../coverage/api/doorkeeper/test-results.xml
+api-doorkeeper.sonar.typescript.tsconfigPath=tsconfig.build.json
-registries-health.sonar.projectName=NDS-REGISTRIES-HEALTH-Typescript
-registries-health.sonar.projectBaseDir=packages/registries/health
-registries-health.sonar.sources=src
-registries-health.sonar.inclusions=src/**/*
-registries-health.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-registries-health.sonar.test.inclusions=src/**/*.test.ts
-registries-health.sonar.javascript.lcov.reportPaths=../../../coverage/registries/health/lcov.info
-registries-health.sonar.junit.reportPaths=../../../coverage/registries/health/test-results.xml
-registries-health.sonar.typescript.tsconfigPath=tsconfig.build.json
+api-crash.sonar.projectName=NDS-API-CRASH-Typescript
+api-crash.sonar.projectBaseDir=packages/api/crash
+api-crash.sonar.sources=src
+api-crash.sonar.inclusions=src/**/*
+api-crash.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+api-crash.sonar.test.inclusions=src/**/*.test.ts
+api-crash.sonar.javascript.lcov.reportPaths=../../../coverage/api/crash/lcov.info
+api-crash.sonar.junit.reportPaths=../../../coverage/api/crash/test-results.xml
+api-crash.sonar.typescript.tsconfigPath=tsconfig.build.json
-registries-metrics.sonar.projectName=NDS-REGISTRIES-METRICS-Typescript
-registries-metrics.sonar.projectBaseDir=packages/registries/metrics
-registries-metrics.sonar.sources=src
-registries-metrics.sonar.inclusions=src/**/*
-registries-metrics.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts
-registries-metrics.sonar.test.inclusions=src/**/*.test.ts
-registries-metrics.sonar.javascript.lcov.reportPaths=../../../coverage/registries/metrics/lcov.info
-registries-metrics.sonar.junit.reportPaths=../../../coverage/registries/metrics/test-results.xml
-registries-metrics.sonar.typescript.tsconfigPath=tsconfig.build.json
\ No newline at end of file
+api-core.sonar.projectName=NDS-API-CORE-Typescript
+api-core.sonar.projectBaseDir=packages/api/core
+api-core.sonar.sources=src
+api-core.sonar.inclusions=src/**/*
+api-core.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts
+api-core.sonar.test.inclusions=src/**/*.test.ts
+api-core.sonar.javascript.lcov.reportPaths=../../../coverage/api/core/lcov.info
+api-core.sonar.junit.reportPaths=../../../coverage/api/core/test-results.xml
+api-core.sonar.typescript.tsconfigPath=tsconfig.build.json
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 50e82850..69d465eb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
+yarn.lock
+
# compiled output
**/dist
/tmp
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 27628caa..1c2133ae 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -60,7 +60,9 @@
"openc2",
"app-wrapper",
"ci",
- "doorkeeper"
+ "doorkeeper",
+ "faker",
+ "kafka-provider"
],
}
diff --git a/createSonarConfig.js b/createSonarConfig.js
deleted file mode 100644
index f17e0f3a..00000000
--- a/createSonarConfig.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Copyright 2022 Mytra Control S.L. All rights reserved.
- *
- * Use of this source code is governed by an MIT-style license that can be found in the LICENSE file
- * or at https://opensource.org/licenses/MIT.
- */
-const fs = require('fs');
-const glob = require('glob');
-glob("packages/*/*", (err, folders) => {
- console.log(folders);
- fs.writeFileSync('sonar-project.properties', `sonar.projectKey=Mytra-Development-Framework-NDF-TypeScript\n`);
- fs.appendFileSync('sonar-project.properties', `sonar.projectName=Mytra Development Framework - NDF - TypeScript\n`);
- fs.appendFileSync('sonar-project.properties', `sonar.modules=${folders.map((folder) => {
- const parts = folder.split('/');
- return `${parts[parts.length - 2]}-${parts[parts.length - 1]}`;
- }).join(',')}\n`);
- fs.appendFileSync('sonar-project.properties', 'sonar.exclusions=coveragereport/**/*,packages/**/*.test.ts,packages/**/test/*.ts,packages/**/*.js\n\n');
- for (const folder of folders) {
- const parts = folder.split('/');
- const subFolderPath = `${parts[parts.length - 2]}/${parts[parts.length - 1]}`;
- const moduleName = `${parts[parts.length - 2]}-${parts[parts.length - 1]}`;
- fs.appendFileSync('sonar-project.properties', `${moduleName}.sonar.projectName=NDS-${moduleName.toLocaleUpperCase()}-Typescript\n`);
- fs.appendFileSync('sonar-project.properties', `${moduleName}.sonar.projectBaseDir=${folder}\n`);
- fs.appendFileSync('sonar-project.properties', `${moduleName}.sonar.sources=src\n`);
- fs.appendFileSync('sonar-project.properties', `${moduleName}.sonar.inclusions=src/**/*\n`);
- fs.appendFileSync('sonar-project.properties', `${moduleName}.sonar.inclusions=src/**/*.test.ts,src/**/test/*.ts\n`);
- fs.appendFileSync('sonar-project.properties', `${moduleName}.sonar.test.inclusions=src/**/*.test.ts\n`);
- fs.appendFileSync('sonar-project.properties', `${moduleName}.sonar.javascript.lcov.reportPaths=../../../coverage/${subFolderPath}/lcov.info\n`);
- fs.appendFileSync('sonar-project.properties', `${moduleName}.sonar.junit.reportPaths=../../../coverage/${subFolderPath}/test-results.xml\n`);
- fs.appendFileSync('sonar-project.properties', `${moduleName}.sonar.typescript.tsconfigPath=tsconfig.build.json\n\n`);
- }
-})
diff --git a/createSonarConfig.mjs b/createSonarConfig.mjs
new file mode 100644
index 00000000..7de26e04
--- /dev/null
+++ b/createSonarConfig.mjs
@@ -0,0 +1,35 @@
+/**
+ * Copyright 2022 Mytra Control S.L. All rights reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be found in the LICENSE file
+ * or at https://opensource.org/licenses/MIT.
+ */
+
+const fileName = './sonar-project.properties';
+
+import fs from 'fs';
+import { globSync } from 'glob';
+
+const folders = globSync("packages/*/*");
+console.log(folders);
+fs.writeFileSync(fileName, `sonar.projectKey=Mytra-Development-Framework-NDF-TypeScript\n`);
+fs.appendFileSync(fileName, `sonar.projectName=Mytra Development Framework - NDF - TypeScript\n`);
+fs.appendFileSync(fileName, `sonar.modules=${folders.map((folder) => {
+ const parts = folder.split('/');
+ return `${parts[parts.length - 2]}-${parts[parts.length - 1]}`;
+}).join(',')}\n`);
+fs.appendFileSync(fileName, 'sonar.exclusions=coveragereport/**/*,packages/**/*.test.ts,packages/**/test/*.ts,packages/**/*.js\n\n');
+for (const folder of folders) {
+ const parts = folder.split('/');
+ const subFolderPath = `${parts[parts.length - 2]}/${parts[parts.length - 1]}`;
+ const moduleName = `${parts[parts.length - 2]}-${parts[parts.length - 1]}`;
+ fs.appendFileSync(fileName, `${moduleName}.sonar.projectName=NDS-${moduleName.toLocaleUpperCase()}-Typescript\n`);
+ fs.appendFileSync(fileName, `${moduleName}.sonar.projectBaseDir=${folder}\n`);
+ fs.appendFileSync(fileName, `${moduleName}.sonar.sources=src\n`);
+ fs.appendFileSync(fileName, `${moduleName}.sonar.inclusions=src/**/*\n`);
+ fs.appendFileSync(fileName, `${moduleName}.sonar.exclusions=src/**/*.test.ts,src/**/test/*.ts\n`);
+ fs.appendFileSync(fileName, `${moduleName}.sonar.test.inclusions=src/**/*.test.ts\n`);
+ fs.appendFileSync(fileName, `${moduleName}.sonar.javascript.lcov.reportPaths=../../../coverage/${subFolderPath}/lcov.info\n`);
+ fs.appendFileSync(fileName, `${moduleName}.sonar.junit.reportPaths=../../../coverage/${subFolderPath}/test-results.xml\n`);
+ fs.appendFileSync(fileName, `${moduleName}.sonar.typescript.tsconfigPath=tsconfig.build.json\n\n`);
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 76e03ae6..3a3e5774 100644
--- a/package.json
+++ b/package.json
@@ -25,16 +25,16 @@
},
"devDependencies": {
"@mdf.js/repo-config": "*",
- "@stryker-mutator/core": "^6.4.2",
- "@stryker-mutator/jest-runner": "^6.4.2",
- "@stryker-mutator/typescript-checker": "^6.4.2",
- "@types/jest": "29.5.1",
- "@types/node": "20.2.4",
- "@typescript-eslint/eslint-plugin": "5.59.7",
- "@typescript-eslint/parser": "5.59.7",
+ "@stryker-mutator/core": "^7.0.2",
+ "@stryker-mutator/jest-runner": "^7.0.2",
+ "@stryker-mutator/typescript-checker": "^7.0.2",
+ "@types/jest": "29.5.2",
+ "@types/node": "20.3.1",
+ "@typescript-eslint/eslint-plugin": "5.59.11",
+ "@typescript-eslint/parser": "5.59.11",
"cross-env": "^7.0.3",
"dependency-cruiser": "^13.0.2",
- "eslint": "~8.41.0",
+ "eslint": "~8.42.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-prettier": "^4.2.1",
@@ -45,7 +45,7 @@
"jest-html-reporter": "^3.10.0",
"jest-junit": "^16.0.0",
"jest-slow-test-reporter": "^1.0.0",
- "lerna": "^6.6.2",
+ "lerna": "^7.0.2",
"license-checker": "^25.0.1",
"npm-check": "^6.0.1",
"prettier": "^2.8.8",
@@ -56,7 +56,7 @@
"ts-jest": "29.1.0",
"ts-node": "10.9.1",
"turbo": "^1.9.9",
- "typedoc": "0.24.7",
- "typescript": "5.0.4"
+ "typedoc": "0.24.8",
+ "typescript": "5.1.3"
}
}
diff --git a/packages/api/core/src/Layer/Provider/Manager.ts b/packages/api/core/src/Layer/Provider/Manager.ts
index 3acae464..092cd182 100644
--- a/packages/api/core/src/Layer/Provider/Manager.ts
+++ b/packages/api/core/src/Layer/Provider/Manager.ts
@@ -78,7 +78,7 @@ export class Manager T,
+ port: new (portConfig: PortConfig, logger: LoggerInstance) => T,
private readonly options: ProviderOptions,
config?: Partial
) {
diff --git a/packages/api/crash/src/Boom/BoomError.ts b/packages/api/crash/src/Boom/BoomError.ts
index 49cf1e0a..75af2f76 100644
--- a/packages/api/crash/src/Boom/BoomError.ts
+++ b/packages/api/crash/src/Boom/BoomError.ts
@@ -103,7 +103,7 @@ export class Boom extends Base {
* @deprecated - `source` has been deprecated, use resource instead
*/
get source(): APISource | undefined {
- return this.resource;
+ return this._source;
}
/** Object with the key information of the requested resource in the REST API context */
get resource(): APISource | undefined {
diff --git a/packages/api/crash/src/Multi/MultiError.ts b/packages/api/crash/src/Multi/MultiError.ts
index 2c25ec62..1f03ddfe 100644
--- a/packages/api/crash/src/Multi/MultiError.ts
+++ b/packages/api/crash/src/Multi/MultiError.ts
@@ -55,29 +55,38 @@ export class Multi extends Base {
* @param options - enhanced error options
*/
constructor(message: string, uuid: string, options: MultiOptions);
- constructor(message: string, uuid?: string | MultiOptions, options?: MultiOptions) {
- super(message, uuid, options);
- // *****************************************************************************************
- // #region causes type safe
- if (this._options && this._options['causes'] !== undefined) {
- if (this._options['causes'] instanceof Crash || this._options['causes'] instanceof Error) {
- this._causes = [this._options['causes']];
- } else if (!Array.isArray(this._options['causes'])) {
- throw new Base('Options[causes] must be an array of Error/Crash', uuid);
- } else {
- for (const cause of this._options['causes']) {
- if (!(cause instanceof Crash || cause instanceof Error)) {
- throw new Base('Options[causes] must be an array of Error/Crash', uuid);
- }
- }
- this._causes = this._options['causes'];
- }
- }
- // #endregion
+ constructor(message: string, uuidOrOptions?: string | MultiOptions, options?: MultiOptions) {
+ super(message, uuidOrOptions, options);
+ this._causes = this.extractCauses(this._uuid, this._options);
if (this.name === 'BaseError') {
this.name = 'MultiError';
}
}
+ /**
+ * Extract the causes from the options
+ * @param uuid - unique identifier for this particular occurrence of the problem
+ * enhanced error options
+ * @param options - enhanced error options
+ * @returns
+ */
+ private extractCauses(uuid: string, options?: MultiOptions): Cause[] | undefined {
+ if (!options || options['causes'] === undefined) {
+ return;
+ }
+ const causes = options['causes'];
+ if (!(causes instanceof Crash || causes instanceof Error) && !Array.isArray(causes)) {
+ throw new Base('Options[causes] must be an array of Error/Crash', uuid);
+ }
+ if (causes instanceof Crash || causes instanceof Error) {
+ return [causes];
+ }
+ for (const cause of causes) {
+ if (!(cause instanceof Crash || cause instanceof Error)) {
+ throw new Base('Options[causes] must be an array of Error/Crash', uuid);
+ }
+ }
+ return causes;
+ }
/** Determine if this instance is a Multi error */
get isMulti(): boolean {
return this._isMulti;
diff --git a/packages/api/doorkeeper/src/Doorkeeper.ts b/packages/api/doorkeeper/src/Doorkeeper.ts
index ffee09d9..8b283035 100644
--- a/packages/api/doorkeeper/src/Doorkeeper.ts
+++ b/packages/api/doorkeeper/src/Doorkeeper.ts
@@ -267,15 +267,14 @@ export class DoorKeeper {
this.checkSchema(schema, data, uuid);
} catch (rawError) {
error = Crash.from(rawError);
- } finally {
- if (callback) {
- callback(error, data);
+ }
+ if (callback) {
+ callback(error, data);
+ } else {
+ if (error) {
+ return Promise.reject(error);
} else {
- if (error) {
- return Promise.reject(error);
- } else {
- return Promise.resolve(data);
- }
+ return Promise.resolve(data);
}
}
}
diff --git a/packages/api/doorkeeper/typedoc.json b/packages/api/doorkeeper/typedoc.json
new file mode 100644
index 00000000..3d76d423
--- /dev/null
+++ b/packages/api/doorkeeper/typedoc.json
@@ -0,0 +1,33 @@
+{
+ "entryPoints": [
+ "src/index.ts"
+ ],
+ "tsconfig": "./tsconfig.build.json",
+ "entryPointStrategy": "resolve",
+ "exclude": [
+ "**/dist/**",
+ "**/node_modules",
+ "src/**/*.test.ts",
+ "src/**/test/*.*"
+ ],
+ "externalPattern": ["**/node_modules/**"],
+ "excludeExternals": true,
+ "excludePrivate": true,
+ "excludeProtected": true,
+ "excludeInternal": true,
+ "includes": [],
+ "media": "media",
+ "out": "../../../docs/api/doorkeeper",
+ "markedOptions": {
+ "gfm": true
+ },
+ "name": "@mdf.js/doorkeeper",
+ "includeVersion": true,
+ "disableSources": true,
+ "excludeTags": [],
+ "readme": "README.md",
+ "categorizeByGroup": false,
+ "categoryOrder": [],
+ "cleanOutputDir": true,
+ "gitRevision": "master",
+}
diff --git a/packages/api/faker/.eslintignore b/packages/api/faker/.eslintignore
new file mode 100644
index 00000000..1fb0aaeb
--- /dev/null
+++ b/packages/api/faker/.eslintignore
@@ -0,0 +1,3 @@
+.eslintrc.js
+stryker.conf.js
+jest.config.js
\ No newline at end of file
diff --git a/packages/api/faker/.eslintrc.js b/packages/api/faker/.eslintrc.js
new file mode 100644
index 00000000..9dc3b286
--- /dev/null
+++ b/packages/api/faker/.eslintrc.js
@@ -0,0 +1,7 @@
+/**
+ * Copyright 2022 Mytra Control S.L. All rights reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be found in the LICENSE file
+ * or at https://opensource.org/licenses/MIT.
+ */
+module.exports = require('@mdf.js/repo-config').getEslintConfig();
diff --git a/packages/api/faker/README.md b/packages/api/faker/README.md
new file mode 100644
index 00000000..7553fbf7
--- /dev/null
+++ b/packages/api/faker/README.md
@@ -0,0 +1,303 @@
+# **@mdf.js/faker**
+
+[![Node Version](https://img.shields.io/static/v1?style=flat&logo=node.js&logoColor=green&label=node&message=%3E=16%20||%2018&color=blue)](https://nodejs.org/en/)
+[![Typescript Version](https://img.shields.io/static/v1?style=flat&logo=typescript&label=Typescript&message=4.8&color=blue)](https://www.typescriptlang.org/)
+[![Known Vulnerabilities](https://img.shields.io/static/v1?style=flat&logo=snyk&label=Vulnerabilities&message=0&color=300A98F)](https://snyk.io/package/npm/snyk)
+
+
+
+
+
+
+
+
+Mytra Development Framework - @mdf.js
+Typescript tools for development
+
+
+
+---
+
+## **Table of contents**
+
+- [**@mdf.js/faker**](#mdfjsfaker)
+ - [**Table of contents**](#table-of-contents)
+ - [**Introduction**](#introduction)
+ - [**Installation**](#installation)
+ - [**Information**](#information)
+ - [Programmatic Generation of Attributes](#programmatic-generation-of-attributes)
+ - [Batch Specification of Attributes](#batch-specification-of-attributes)
+ - [Post Build Callback](#post-build-callback)
+ - [Associate a Factory with an existing Class](#associate-a-factory-with-an-existing-class)
+ - [**Use**](#use)
+ - [**License**](#license)
+
+## **Introduction**
+
+Faker is a tool to generate fake data for testing purposes based on [rosie](https://www.npmjs.com/package/rosie) package with some improvements.
+
+To use `@mdf.js/faker` you first define a factory. The factory is defined in terms of attributes, sequences, options, callbacks, and can inherit from other factories. Once the factory is defined you use it to build objects.
+
+## **Installation**
+
+- **npm**
+
+```bash
+npm install @mdf.js/faker
+```
+
+- **yarn**
+
+```bash
+yarn add @mdf.js/faker
+```
+
+## **Information**
+
+There are two phases of use:
+
+1. Factory definition
+2. Object building
+
+**Factory Definition:** Define a factory, specifying attributes, sequences, options, and callbacks:
+
+```typescript
+import { Factory } from '@mdf.js/faker';
+interface Player {
+ id: number;
+ name: string;
+ position: string;
+}
+
+interface Game {
+ id: number;
+ is_over: boolean;
+ created_at: Date;
+ random_seed: number;
+ players: Player[];
+}
+
+const playerFactory = new Factory()
+ .sequence('id')
+ .sequence('name', i => {
+ return 'player' + i;
+ })
+
+ // Define `position` to depend on `id`.
+ .attr('position', ['id'], id => {
+ const positions = ['pitcher', '1st base', '2nd base', '3rd base'];
+ return positions[id % positions.length];
+ });
+
+const gameFactory = new Factory()
+ .sequence('id')
+ .attr('is_over', false)
+ .attr('created_at', () => new Date())
+ .attr('random_seed', () => Math.random())
+ // Default to two players. If players were given, fill in
+ // whatever attributes might be missing.
+ .attr('players', ['players'], players => {
+ if (!players) {
+ players = [{}, {}];
+ }
+ return players.map(data => playerFactory.build(data));
+ });
+
+const disabledPlayer = new Factory().extend(playerFactory).attr('state', 'disabled');
+```
+
+**Object Building:** Build an object, passing in attributes that you want to override:
+
+```js
+const game = gameFactory.build({ is_over: true });
+// Built object (note scores are random):
+//{
+// id: 1,
+// is_over: true, // overriden when building
+// created_at: Fri Apr 15 2011 12:02:25 GMT-0400 (EDT),
+// random_seed: 0.8999513240996748,
+// players: [
+// {id: 1, name:'Player 1'},
+// {id: 2, name:'Player 2'}
+// ]
+//}
+```
+
+### Programmatic Generation of Attributes
+
+You can specify options that are used to programmatically generate the attributes:
+
+```typescript
+import { Factory } from '@mdf.js/faker';
+import moment from 'moment';
+
+interface Match {
+ matchDate: string;
+ homeScore: number;
+ awayScore: number;
+}
+
+const matchFactory = new Factory()
+ .attr('seasonStart', '2016-01-01')
+ .option('numMatches', 2)
+ .attr('matches', ['numMatches', 'seasonStart'], (numMatches, seasonStart) => {
+ const matches = [];
+ for (const i = 1; i <= numMatches; i++) {
+ matches.push({
+ matchDate: moment(seasonStart).add(i, 'week').format('YYYY-MM-DD'),
+ homeScore: Math.floor(Math.random() * 5),
+ awayScore: Math.floor(Math.random() * 5),
+ });
+ }
+ return matches;
+ });
+
+matchFactory.build({ seasonStart: '2016-03-12' }, { numMatches: 3 });
+// Built object (note scores are random):
+//{
+// seasonStart: '2016-03-12',
+// matches: [
+// { matchDate: '2016-03-19', homeScore: 3, awayScore: 1 },
+// { matchDate: '2016-03-26', homeScore: 0, awayScore: 4 },
+// { matchDate: '2016-04-02', homeScore: 1, awayScore: 0 }
+// ]
+//}
+```
+
+In the example `numMatches` is defined as an `option`, not as an `attribute`. Therefore `numMatches` is not part of the output, it is only used to generate the `matches` array.
+
+In the same example `seasonStart` is defined as an `attribute`, therefore it appears in the output, and can also be used in the generator function that creates the `matches` array.
+
+### Batch Specification of Attributes
+
+The convenience function `attrs` simplifies the common case of specifying multiple attributes in a batch. Rewriting the `game` example from above:
+
+```typescript
+const gameFactory = new Factory()
+ .sequence('id')
+ .attrs({
+ is_over: false,
+ created_at: () => new Date(),
+ random_seed: () => Math.random(),
+ })
+ .attr('players', ['players'], players => {
+ /* etc. */
+ });
+```
+
+### Post Build Callback
+
+You can also define a callback function to be run after building an object:
+
+```typescript
+interface Coach {
+ id: number;
+ players: Player[];
+}
+
+const coachFactory = new Factory()
+ .option('buildPlayer', false)
+ .sequence('id')
+ .attr('players', ['id', 'buildPlayer'], (id, buildPlayer) => {
+ if (buildPlayer) {
+ return [Factory.build('player', { coach_id: id })];
+ }
+ })
+ .after((coach, options) => {
+ if (options.buildPlayer) {
+ console.log('built player:', coach.players[0]);
+ }
+ });
+
+Factory.build({}, { buildPlayer: true });
+```
+
+Multiple callbacks can be registered, and they will be executed in the order they are registered. The callbacks can manipulate the built object before it is returned to the callee.
+
+If the callback doesn't return anything, `@mdf.js/faker` will return build object as final result. If the callback returns a value, `@mdf.js/faker` will use that as final result instead.
+
+### Associate a Factory with an existing Class
+
+This is an advanced use case that you can probably happily ignore, but store this away in case you need it.
+
+When you define a factory you can optionally provide a class definition, and anything built by the factory will be passed through the constructor of the provided class.
+
+Specifically, the output of `.build` is used as the input to the constructor function, so the returned object is an instance of the specified class:
+
+```js
+class SimpleClass {
+ constructor(args) {
+ this.moops = 'correct';
+ this.args = args;
+ }
+
+ isMoopsCorrect() {
+ return this.moops;
+ }
+}
+
+testFactory = Factory.define('test', SimpleClass).attr('some_var', 4);
+
+testInstance = testFactory.build({ stuff: 2 });
+console.log(JSON.stringify(testInstance, {}, 2));
+// Output:
+// {
+// "moops": "correct",
+// "args": {
+// "stuff": 2,
+// "some_var": 4
+// }
+// }
+
+console.log(testInstance.isMoopsCorrect());
+// Output:
+// correct
+```
+
+Mind. Blown.
+
+## **Use**
+
+To use `@mdf.js/faker` in node, you'll need to import it first:
+
+```js
+import { Factory } from '@mdf.js/faker';
+// or with `require`
+const Factory = require('@mdf.js/faker').Factory;
+```
+
+You might also choose to use unregistered factories, as it fits better with node's module pattern:
+
+```typescript
+// factories/game.js
+import { Factory } from '@mdf.js/faker';
+
+export default new Factory().sequence('id').attr('is_over', false);
+// etc
+```
+
+To use the unregistered `Game` factory defined above:
+
+```js
+import Game from './factories/game';
+
+const game = Game.build({ is_over: true });
+```
+
+You can also extend an existing unregistered factory:
+
+```js
+// factories/scored-game.js
+import { Factory } from '@mdf.js/faker';
+import Game from './game';
+
+export default new Factory().extend(Game).attrs({
+ score: 10,
+});
+```
+
+## **License**
+
+Copyright 2022 Mytra Control S.L. All rights reserved.
+
+Use of this source code is governed by an MIT-style license that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
diff --git a/packages/api/faker/jest.config.js b/packages/api/faker/jest.config.js
new file mode 100644
index 00000000..99bc7e96
--- /dev/null
+++ b/packages/api/faker/jest.config.js
@@ -0,0 +1,7 @@
+/**
+ * Copyright 2022 Mytra Control S.L. All rights reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be found in the LICENSE file
+ * or at https://opensource.org/licenses/MIT.
+ */
+module.exports = require('@mdf.js/repo-config').getJestConfig(__dirname);
diff --git a/packages/api/faker/package.json b/packages/api/faker/package.json
new file mode 100644
index 00000000..71332fda
--- /dev/null
+++ b/packages/api/faker/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "@mdf.js/faker",
+ "version": "0.0.1",
+ "description": "MMS - API - Faker",
+ "keywords": [
+ "NodeJS",
+ "MMS",
+ "API",
+ "Faker"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/mytracontrol/mdf.js.git",
+ "directory": "packages/api/faker"
+ },
+ "license": "MIT",
+ "author": "Mytra Control S.L.",
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "files": [
+ "dist/**/*"
+ ],
+ "scripts": {
+ "build": "yarn clean && tsc -p tsconfig.build.json",
+ "check-dependencies": "npm-check",
+ "doc": "typedoc --options typedoc.json",
+ "clean": "rimraf \"{tsconfig.build.tsbuildinfo,dist}\"",
+ "licenses": "license-checker --start ./ --production --csv --out ../../../licenses/api/doorkeeper/licenses.csv --customPath ../../../.config/customFormat.json",
+ "mutants": "stryker run stryker.conf.js",
+ "test": "jest --detectOpenHandles --config ./jest.config.js"
+ },
+ "dependencies": {
+ "@mdf.js/crash": "*",
+ "lodash": "^4.17.21",
+ "chance": "^1.1.11"
+ },
+ "devDependencies": {
+ "@types/lodash": "^4.14.195",
+ "@types/chance": "^1.1.3"
+ },
+ "engines": {
+ "node": ">=16.14.2"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/packages/api/faker/src/Factory.test.ts b/packages/api/faker/src/Factory.test.ts
new file mode 100644
index 00000000..e046d925
--- /dev/null
+++ b/packages/api/faker/src/Factory.test.ts
@@ -0,0 +1,253 @@
+/**
+ * Copyright 2022 Mytra Control S.L. All rights reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be found in the LICENSE file
+ * or at https://opensource.org/licenses/MIT.
+ */
+
+import { Factory } from './Factory';
+describe('#Faker #package', () => {
+ describe('#Happy path', () => {
+ it('Should be able to create a new instance', () => {
+ expect(new Factory()).toBeInstanceOf(Factory);
+ });
+ it('Should be able to create a new instance and add some attributes one by one with default values', () => {
+ const factory = new Factory();
+ factory.attr('name', 'John');
+ factory.attr('age', 24);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build()).toEqual({ name: 'John', age: 24 });
+ });
+ it('Should be able to create a new instance and add some attributes one by one with custom values', () => {
+ const factory = new Factory();
+ factory.attr('name', 'John');
+ factory.attr('age');
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build({ name: 'Jane', age: 24 })).toEqual({ name: 'Jane', age: 24 });
+ });
+ it('Should be able to create a new instance and add some attributes one by one with generators', () => {
+ const factory = new Factory();
+ factory.attr('name', () => 'John');
+ factory.attr('age', () => 24);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build()).toEqual({ name: 'John', age: 24 });
+ });
+ it('Should be able to create a new instance and add some attributes one by one with generators and custom values', () => {
+ const factory = new Factory();
+ factory.attr('name', () => 'John');
+ factory.attr('age', () => 24);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build({ name: 'Jane' })).toEqual({ name: 'Jane', age: 24 });
+ });
+ it('Should be able to create a new instance and add some attributes in bulk with default values', () => {
+ const factory = new Factory();
+ factory.attrs({ name: 'John', age: 24 });
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build()).toEqual({ name: 'John', age: 24 });
+ });
+ it(`Should be able to create a new instance and add some attributes based in options`, () => {
+ const factory = new Factory();
+ factory.option('name', () => 'John');
+ factory.attr('surname', () => 'Doe');
+ factory.attr('completeName', ['name', 'surname'], (name, surname) => `${name} ${surname}`);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build()).toEqual({ surname: 'Doe', completeName: 'John Doe' });
+ });
+ it(`Should be able to create a new instance and add some attributes based in options with custom values`, () => {
+ const factory = new Factory();
+ factory.option('name', () => 'John');
+ factory.attr('surname', () => 'Doe');
+ factory.attr('completeName', ['name', 'surname'], (name, surname) => `${name} ${surname}`);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build({}, { name: 'Jane' })).toEqual({
+ surname: 'Doe',
+ completeName: 'Jane Doe',
+ });
+ });
+ it(`Should be able to create a new instance and add some sequence attributes`, () => {
+ const factory = new Factory();
+ factory.sequence('id');
+ factory.attr('name', ['id'], id => `John ${id}`);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build()).toEqual({ id: 1, name: 'John 1' });
+ expect(factory.build()).toEqual({ id: 2, name: 'John 2' });
+ });
+ it(`Should be able to create a new instance and add some sequence attributes and reset the sequence`, () => {
+ const factory = new Factory();
+ factory.sequence('id');
+ factory.attr('name', ['id'], id => `John ${id}`);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build()).toEqual({ id: 1, name: 'John 1' });
+ expect(factory.build()).toEqual({ id: 2, name: 'John 2' });
+ factory.reset();
+ expect(factory.build()).toEqual({ id: 1, name: 'John 1' });
+ expect(factory.build()).toEqual({ id: 2, name: 'John 2' });
+ });
+ it(`Should be able to create a new instance and add some sequence attributes with custom values`, () => {
+ const factory = new Factory();
+ factory.sequence('id');
+ factory.attr('name', ['id'], id => `John ${id}`);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build({ id: 3 })).toEqual({ id: 3, name: 'John 3' });
+ expect(factory.build({ id: 4 })).toEqual({ id: 4, name: 'John 4' });
+ });
+ it(`Should be able to create a new instance and add some sequence attributes with custom generator`, () => {
+ const factory = new Factory();
+ factory.sequence('id', i => i + 2);
+ factory.attr('name', ['id'], id => `John ${id}`);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build()).toEqual({ id: 2, name: 'John 2' });
+ expect(factory.build()).toEqual({ id: 4, name: 'John 4' });
+ });
+ it(`Should be able to create a new instance and add some sequence attributes with custom generator with dependencies`, () => {
+ const factory = new Factory();
+ factory.option('seed', () => 10);
+ factory.sequence('id', ['seed'], (i, seed) => seed + i + 2);
+ factory.attr('name', ['id'], id => `John ${id}`);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build()).toEqual({ id: 12, name: 'John 12' });
+ expect(factory.build()).toEqual({ id: 24, name: 'John 24' });
+ });
+ it(`Should be able to create a new instance and modify the final result object with after callback`, () => {
+ const factory = new Factory<{ name: string }>();
+ factory.option('times', () => 2);
+ factory.attr('name', 'John');
+ factory.after((object, options) => {
+ object.name = `${object.name} ${options['times']}`;
+ return object;
+ });
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build()).toEqual({ name: 'John 2' });
+ });
+ it(`Should be able to create several object with 'buildList' method of a instance`, () => {
+ const factory = new Factory();
+ factory.option('times', () => 2);
+ factory.attr('name', ['times'], times => `John ${times}`);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.buildList(2)).toEqual([{ name: 'John 2' }, { name: 'John 2' }]);
+ });
+ it(`Should be able to create several object with 'buildList' method of a instance with custom values`, () => {
+ const factory = new Factory();
+ factory.option('times', () => 2);
+ factory.attr('name', ['times'], times => `John ${times}`);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.buildList(2, { name: 'Jane' })).toEqual([{ name: 'Jane' }, { name: 'Jane' }]);
+ });
+ it(`Should be able to create several object with 'buildList' method of a instance with custom values and options`, () => {
+ const factory = new Factory();
+ factory.option('times', () => 2);
+ factory.attr('name', ['times'], times => `John ${times}`);
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.buildList(2, {}, { times: 3 })).toEqual([
+ { name: 'John 3' },
+ { name: 'John 3' },
+ ]);
+ });
+ it(`Should be able to extend a factory instance with new attributes and options`, () => {
+ const factory = new Factory();
+ factory.option('times', () => 2);
+ factory.attr('name', ['times'], times => `John ${times}`);
+ const extendedFactory = new Factory().extend(factory);
+ extendedFactory.option('times', () => 3);
+ extendedFactory.attr('surname', () => 'Doe');
+ expect(extendedFactory).toBeInstanceOf(Factory);
+ expect(extendedFactory.build()).toEqual({ name: 'John 3', surname: 'Doe' });
+ });
+ it(`Should be able to generate wrong data if the likelihood is not 100`, () => {
+ const factory = new Factory();
+ factory.option('seed', () => 10);
+ factory.attr('surname', 'Doe');
+ factory.attr('age', ['seed'], seed => seed + 14);
+ const result = { surname: 'Doe', age: 24 };
+ expect(factory).toBeInstanceOf(Factory);
+ for (let i = 0; i < 100; i++) {
+ expect(factory.build({}, { likelihood: 100 })).toEqual(result);
+ expect(factory.build({}, { likelihood: 0 })).not.toEqual(result);
+ }
+ });
+ it(`Should be possible to generate complex instances with several nested objects that are generated by other factories`, () => {
+ const johnFactory = new Factory();
+ johnFactory.attr('name', () => 'John');
+ johnFactory.attr('surname', () => 'Doe');
+ johnFactory.attr('age', () => 24);
+ const janeFactory = new Factory();
+ janeFactory.attr('name', () => 'Jane');
+ janeFactory.attr('surname', () => 'Doe');
+ janeFactory.attr('age', () => 24);
+
+ const userFactory = new Factory();
+ userFactory.option('name', 'John');
+ userFactory.after((object, options) => {
+ if (options['name'] === 'John') {
+ return johnFactory.build();
+ }
+ return janeFactory.build();
+ });
+
+ const addressFactory = new Factory();
+ addressFactory.option('name', 'John');
+ addressFactory.attr('street', ['name'], name => `${name} Street`);
+ addressFactory.attr('number', ['name'], name => `${name} Number`);
+ addressFactory.attr('city', ['country'], country => `${country} City`);
+ addressFactory.attr('country', () => 'Fake Country');
+
+ const factory = new Factory();
+ factory.option('name', 'John');
+ factory.attr('user', ['name'], name => userFactory.build({}, { name }));
+ factory.attr('address', ['user'], user => addressFactory.build({}, { name: user.surname }));
+ expect(factory).toBeInstanceOf(Factory);
+ expect(factory.build()).toEqual({
+ user: { name: 'John', surname: 'Doe', age: 24 },
+ address: {
+ street: 'Doe Street',
+ number: `Doe Number`,
+ city: 'Fake Country City',
+ country: 'Fake Country',
+ },
+ });
+ });
+ });
+ describe('#Sad path', () => {
+ it('Should throw an error if no attributes are set', () => {
+ const factory = new Factory();
+ // @ts-expect-error Testing purposes
+ expect(() => factory.attr('a', 9, () => 'John')).toThrowError(
+ 'Dependencies must be an array'
+ );
+ });
+ it('Should throw an error if the dependencies are not an array', () => {
+ const factory = new Factory();
+ // @ts-expect-error Testing purposes
+ expect(() => factory.attr('a', 9, () => 'John')).toThrowError(
+ 'Dependencies must be an array'
+ );
+ });
+ it('Should throw an error if the dependencies are defined but the generator is not', () => {
+ const factory = new Factory();
+ expect(() => factory.attr('a', ['d'])).toThrowError(
+ 'Generator function is required if dependencies are defined'
+ );
+ });
+ it('Should throw an error if likelihood options is not number', () => {
+ const factory = new Factory();
+ factory.option('name', () => 'John');
+ factory.attr('surname', () => 'Doe');
+ // @ts-expect-error Testing purposes
+ expect(() => factory.build({}, { likelihood: 'a' })).toThrowError(
+ 'Likelihood must be a number between 0 and 100'
+ );
+ expect(() => factory.build({}, { likelihood: 101 })).toThrowError(
+ 'Likelihood must be a number between 0 and 100'
+ );
+ expect(() => factory.build({}, { likelihood: -1 })).toThrowError(
+ 'Likelihood must be a number between 0 and 100'
+ );
+ });
+ it('Should throw an error if there is an dependency cycle', () => {
+ const factory = new Factory();
+ factory.attr('a', ['b'], () => 'John');
+ factory.attr('b', ['a'], () => 'Doe');
+ expect(() => factory.build()).toThrowError('Detect a dependency cycle: b -> a -> b');
+ });
+ });
+});
diff --git a/packages/api/faker/src/Factory.ts b/packages/api/faker/src/Factory.ts
new file mode 100644
index 00000000..a137393c
--- /dev/null
+++ b/packages/api/faker/src/Factory.ts
@@ -0,0 +1,586 @@
+/**
+ * Copyright 2023 Netin Systems S.L. All rights reserved.
+ * Note: All information contained herein is, and remains the property of Netin Systems S.L. and its
+ * suppliers, if any. The intellectual and technical concepts contained herein are property of
+ * Netin Systems S.L. and its suppliers and may be covered by European and Foreign patents, patents
+ * in process, and are protected by trade secret or copyright.
+ *
+ * Dissemination of this information or the reproduction of this material is strictly forbidden
+ * unless prior written permission is obtained from Netin Systems S.L.
+ */
+import { Crash } from '@mdf.js/crash';
+import { Chance } from 'chance';
+import _ from 'lodash';
+
+/** Type for attribute dependencies */
+export type Dependencies = (K | string)[];
+/** Type for function for attribute builder function */
+export type Builder = (...args: any) => T[K] | undefined;
+/** Type for attribute default value */
+export type DefaultValue = T[K];
+/** Type for attribute value option */
+type GeneratorOptions =
+ | Builder
+ | DefaultValue
+ | Dependencies;
+/** Interface for attribute generation */
+interface Entry {
+ dependencies?: Dependencies;
+ builder: Builder;
+}
+/** Interface for default object */
+export interface DefaultObject {
+ [key: string]: any;
+}
+/** Interface for default options */
+export interface DefaultOptions {
+ likelihood?: number;
+ [key: string]: any;
+}
+
+/** Factory for building JavaScript objects, mostly useful for setting up test data */
+export class Factory<
+ T extends DefaultObject = DefaultObject,
+ R extends DefaultOptions = DefaultOptions
+> {
+ /** Options for programmatic generation of attributes */
+ private _opts: {
+ [K in keyof R]: Entry;
+ };
+ /** Attributes of this factory, based on a interface */
+ private _attrs: {
+ [K in keyof T]: Entry;
+ };
+ /** Auto incrementing sequence attribute */
+ private _seques: {
+ [K in keyof T]?: number;
+ };
+ /** Callback function array */
+ private readonly _callbacks: ((object: T, options: { [key: string]: any }) => T | void)[];
+ /** Chance object for probabilistic wrong value generation */
+ private readonly _chance;
+ /** Create a new factory instance */
+ public constructor() {
+ this._opts = {} as { [K in keyof R]: Entry };
+ this._attrs = {} as { [K in keyof T]: Entry };
+ this._seques = {};
+ this._callbacks = [];
+ this._chance = new Chance();
+ }
+ /**
+ * Define an attribute on this factory
+ * @param attr - Name of attribute
+ * @example
+ * ```typescript
+ * factory.attr('name');
+ * ```
+ */
+ public attr(attr: K): Factory;
+ /**
+ * Define an attribute on this factory using a default value (e.g. a string or number)
+ * @param attr - Name of attribute
+ * @param defaultValue - Default value of attribute
+ * @example
+ * ```typescript
+ * factory.attr('name', 'John Doe');
+ * ```
+ */
+ public attr(attr: K, defaultValue: DefaultValue): Factory;
+ /**
+ * Define an attribute on this factory using a generator function
+ * @param attr - Name of attribute
+ * @param generator - Value generator function
+ * @example
+ * ```typescript
+ * factory.attr('name', () => function() { return 'John Doe'; });
+ * ```
+ */
+ public attr(attr: K, generator: Builder): Factory;
+ /**
+ * Define an attribute on this factory using a generator function and dependencies on options or
+ * other attributes
+ * @param attr - Name of attribute
+ * @param dependencies - Array of dependencies as option or attribute names that are used by the
+ * generator function to generate the value of this attribute
+ * @param generator - Value generator function. The generator function will be called with the
+ * resolved values of the dependencies as arguments.
+ * @example
+ * ```typescript
+ * factory.attr('name', ['firstName', 'lastName'], (firstName, lastName) => {
+ * return `${firstName} ${lastName}`;
+ * });
+ * ```
+ */
+ public attr(
+ attr: K,
+ dependencies: Dependencies,
+ generator: Builder
+ ): Factory;
+ public attr(
+ attr: K,
+ generatorOptions?: GeneratorOptions,
+ builder?: Builder
+ ): Factory {
+ this._attrs[attr] = this._SafeType(generatorOptions, builder);
+ return this;
+ }
+ /**
+ * Define multiple attributes on this factory using a default value (e.g. a string or number) or
+ * generator function. If you need to define dependencies on options or other attributes, use the
+ * `attr` method instead.
+ * @param attributes - Object with multiple attributes
+ * @example
+ * ```typescript
+ * factory.attrs({
+ * name: 'John Doe',
+ * age: function() { return 21; },
+ * });
+ * ```
+ */
+ public attrs(attributes: {
+ [K in keyof T]: DefaultValue | Builder;
+ }): Factory {
+ for (const attr in attributes) {
+ if (attributes.hasOwnProperty(attr)) {
+ this.attr(attr, attributes[attr]);
+ }
+ }
+ return this;
+ }
+ /**
+ * Define an option for this factory using a default value. Options are values that are not
+ * directly used in the generated object, but can be used to influence the generation process.
+ * For example, you could define an option `withAddress` that, when set to `true`, would generate
+ * an address and add it to the generated object. Like attributes, options can have dependencies
+ * on other options but not on attributes.
+ * @param opt - Name of option
+ * @param defaultValue - Default value of option
+ * @example
+ * ```typescript
+ * factory.option('withAddress', false);
+ * ```
+ */
+ public option(opt: K, defaultValue: DefaultValue): Factory;
+ /**
+ * Define an option for this factory using a generator function. Options are values that are not
+ * directly used in the generated object, but can be used to influence the generation process.
+ * For example, you could define an option `withAddress` that, when set to `true`, would generate
+ * an address and add it to the generated object. Like attributes, options can have dependencies
+ * on other options but not on attributes.
+ * @param opt - Name of option
+ * @param generator - Value generator function
+ * @example
+ * ```typescript
+ * factory.option('withAddress', () => function() { return false; });
+ * ```
+ */
+ public option(opt: K, generator: Builder): Factory;
+ /**
+ * Define an option for this factory using a generator function with dependencies in other
+ * options. Options are values that are not directly used in the generated object, but can be
+ * used to influence the generation process. For example, you could define an option
+ * `withAddress` that, when set to `true`, would generate an address and add it to the generated
+ * object. Like attributes, options can have dependencies on other options but not on attributes.
+ * @param opt - Name of option
+ * @param dependencies - Array of dependencies as option names that are used by the generator
+ * function to generate the value of this option
+ * @param generator - Value generator function with dependencies in other options. The generator
+ * function will be called with the resolved values of the dependencies as arguments.
+ */
+ public option(
+ opt: K,
+ dependencies: Dependencies,
+ generator: Builder
+ ): Factory;
+ public option(
+ opt: K,
+ generatorOptions: GeneratorOptions,
+ builder?: Builder
+ ): Factory {
+ this._opts[opt] = this._SafeType(generatorOptions, builder);
+ return this;
+ }
+ /**
+ * Define an auto incrementing sequence attribute of the object. Default value is 1.
+ * @param attr - Name of attribute
+ * @example
+ * ```typescript
+ * factory.sequence('id');
+ * ```
+ */
+ public sequence(attr: K): Factory;
+ /**
+ * Define an auto incrementing sequence attribute of the object where the sequence value is
+ * generated by a generator function that is called with the current sequence value as argument.
+ * @param attr - Name of attribute
+ * @param generator - Value generator function
+ * @example
+ * ```typescript
+ * factory.sequence('id', (i) => function() { return i + 11; });
+ * ```
+ */
+ public sequence(attr: K, generator: Builder): Factory;
+ /**
+ * Define an auto incrementing sequence attribute of the object where the sequence value is
+ * generated by a generator function that is called with the current sequence value as argument
+ * and dependencies on options or other attributes.
+ * @param attr - Name of attribute
+ * @param dependencies - Array of dependencies as option or attribute names that are used by the
+ * generator function to generate the value of the sequence attribute
+ * @param generator - Value generator function
+ * @example
+ * ```typescript
+ * factory.sequence('id', ['idPrefix'], (i, idPrefix) => function() {
+ * return `${idPrefix}${i}`;
+ * });
+ * ```
+ */
+ public sequence(
+ attr: K,
+ dependencies: (K | string)[],
+ generator: Builder
+ ): Factory;
+ public sequence(
+ attr: K,
+ generatorOptions?: GeneratorOptions,
+ builder?: Builder
+ ): Factory {
+ const _attribute = this._SafeType(generatorOptions, builder);
+ if (generatorOptions === undefined && builder === undefined) {
+ _attribute.builder = i => i + 1;
+ _attribute.dependencies = [];
+ }
+
+ return this.attr(attr, _attribute.dependencies || [], (...args: any[]) => {
+ const value = _attribute.builder(this._seques[attr] || 0, ...args);
+ this._seques[attr] = value;
+ return value;
+ });
+ }
+ /**
+ * Register a callback function to be called after the object is generated. The callback function
+ * receives the generated object as first argument and the resolved options as second argument.
+ * @param callback - Callback function
+ * @example
+ * ```typescript
+ * factory.after((user) => {
+ * user.name = user.name.toUpperCase();
+ * });
+ * ```
+ */
+ public after(callback: (object: T, options: { [key: string]: any }) => T | void): Factory {
+ this._callbacks.push(callback);
+ return this;
+ }
+ /**
+ * Returns an object that is generated by the factory.
+ * The optional option `likelihood` is a number between 0 and 100 that defines the probability
+ * that the generated object contains wrong data. This is useful for testing if your code can
+ * handle wrong data. The default value is 100, which means that the generated object always
+ * contains correct data.
+ * @param attributes - object containing attribute override key value pairs
+ * @param options - object containing option key value pairs
+ */
+ public build(
+ attributes: { [K in keyof T]?: T[K] } = {},
+ options: { likelihood?: number; [key: string]: any } = { likelihood: 100 }
+ ): T {
+ if (options && options['likelihood'] === undefined) {
+ options = { ...options, likelihood: 100 };
+ }
+ if (
+ typeof options['likelihood'] !== 'number' ||
+ options['likelihood'] < 0 ||
+ options['likelihood'] > 100
+ ) {
+ throw new Crash('Likelihood must be a number between 0 and 100', {
+ likelihood: options['likelihood'],
+ });
+ }
+ const _attributes = _.merge(_.cloneDeep(this._attrs), this._convertToAttributes(attributes));
+ const _options = _.merge(this._opts, this._ConvertToOptions(options));
+ let returnableObject: { [K in keyof T]?: T[K] } = {};
+ const resolvedOptions: { [key: string]: any } = {};
+ for (const attr in this._attrs) {
+ const stack: (keyof T | string)[] = [];
+ returnableObject[attr] = this._Build(
+ _attributes[attr] as Entry,
+ returnableObject,
+ resolvedOptions,
+ _attributes,
+ _options,
+ stack,
+ options['likelihood']
+ );
+ }
+ if (
+ (Object.keys(this._attrs).length === 0 || Object.keys(resolvedOptions).length === 0) &&
+ Object.keys(_options).length > 0
+ ) {
+ for (const opts in _options) {
+ const stack: (keyof T | string)[] = [];
+ resolvedOptions[opts] = this._Build(
+ _options[opts],
+ returnableObject,
+ resolvedOptions,
+ _attributes,
+ _options,
+ stack
+ );
+ }
+ }
+ for (const callback of this._callbacks) {
+ const obj = callback(returnableObject as T, resolvedOptions);
+ if (obj !== undefined) {
+ returnableObject = obj;
+ }
+ }
+ return returnableObject as T;
+ }
+ /**
+ * Returns an array of objects that are generated by the factory.
+ * The optional option `likelihood` is a number between 0 and 100 that defines the probability
+ * that the generated object contains wrong data. This is useful for testing if your code can
+ * handle wrong data. The default value is 100, which means that the generated object always
+ * contains correct data.
+ * @param size - number of objects to generate
+ * @param attributes - object containing attribute override key value pairs
+ * @param options - object containing option key value pairs
+ * @example
+ * ```typescript
+ * factory.buildList(3, { name: 'John Doe' });
+ * ```
+ */
+ public buildList(
+ size: number,
+ attributes: { [K in keyof T]?: T[K] } = {},
+ options: { likelihood?: number; [key: string]: any } = { likelihood: 100 }
+ ): T[] {
+ const objs = [];
+ for (let i = 0; i < size; i++) {
+ objs.push(this.build(attributes, options));
+ }
+ return objs;
+ }
+ /**
+ * Extend this factory with another factory. The attributes and options of the other factory are
+ * merged into this factory. If an attribute or option with the same name already exists, it is
+ * overwritten.
+ * @param factory - Factory to extend this factory with
+ */
+ public extend(factory: Factory): Factory {
+ Object.assign(this._attrs, factory._attrs);
+ Object.assign(this._opts, factory._opts);
+ this._callbacks.push(...factory._callbacks);
+ return this as unknown as Factory
;
+ }
+ /** Reset all the sequences of this factory */
+ public reset(): void {
+ this._seques = {};
+ }
+ /**
+ * Create an object with standard Options from a key-value pairs object
+ * @param options - object containing option key value pairs
+ */
+ private _ConvertToOptions(options: { [key: string]: any }): { [key: string]: Entry } {
+ const opts: { [key: string]: Entry } = {};
+ for (const opt in options) {
+ opts[opt] = { dependencies: undefined, builder: () => options[opt] };
+ }
+ return opts;
+ }
+ /**
+ * Resolve the value of the options or attributes
+ * @param meta - metadata information of option or attribute
+ * @param object - object with resolved attributes
+ * @param resolvedOptions - object with resolved options
+ * @param attributes - attributes object
+ * @param options - options object
+ * @param stack - stack of recursive calls
+ */
+ private _Build(
+ meta: Entry,
+ object: { [K in keyof T]?: T[K] },
+ resolvedOptions: { [key: string]: any },
+ attributes: { [K in keyof T]?: Entry },
+ options: { [key: string]: Entry },
+ stack: (keyof T | string)[],
+ likelihood = 100
+ ): any {
+ if (!meta) {
+ throw new Crash('Error in factory build process', {
+ meta,
+ object,
+ resolvedOptions,
+ attributes,
+ options,
+ stack,
+ });
+ }
+ if (!meta.dependencies) {
+ if (!this._chance.bool({ likelihood })) {
+ return this._wrongData(typeof meta.builder());
+ } else {
+ return meta.builder();
+ }
+ } else {
+ const args = this._BuildWithDependencies(
+ meta.dependencies,
+ object,
+ resolvedOptions,
+ attributes,
+ options,
+ stack
+ );
+ if (!this._chance.bool({ likelihood })) {
+ return this._wrongData(typeof meta.builder(...args));
+ } else {
+ return meta.builder(...args);
+ }
+ }
+ }
+ /**
+ * Resolve the value of the options or attributes if this has dependencies
+ * @param dependencies - option or attribute dependencies
+ * @param object - object with resolved attributes
+ * @param resolvedOptions - object with resolved options
+ * @param attributes - attributes object
+ * @param options - options object
+ * @param stack - stack of recursive calls
+ */
+ private _BuildWithDependencies(
+ dependencies: (string | keyof T)[],
+ object: { [K in keyof T]?: T[K] },
+ resolvedOptions: { [key: string]: any },
+ attributes: { [K in keyof T]?: Entry },
+ options: { [key: string]: Entry },
+ stack: (keyof T | string)[]
+ ): any[] {
+ return dependencies.map(dep => {
+ if (stack.indexOf(dep) >= 0) {
+ throw new Crash(`Detect a dependency cycle: ${stack.concat([dep]).join(' -> ')}`, {
+ stack: stack.concat([dep]),
+ });
+ }
+ let value: any;
+ if (object[dep as keyof T] !== undefined) {
+ value = object[dep as keyof T];
+ } else if (resolvedOptions[dep as string] !== undefined) {
+ value = resolvedOptions[dep as string];
+ } else if (options[dep as string]) {
+ resolvedOptions[dep as string] = this._Build(
+ options[dep as string],
+ object,
+ resolvedOptions,
+ attributes,
+ options,
+ stack.concat([dep])
+ );
+ value = resolvedOptions[dep as string];
+ } else if (attributes[dep as keyof T]) {
+ object[dep as keyof T] = this._Build(
+ attributes[dep as keyof T] as Entry,
+ object,
+ resolvedOptions,
+ attributes,
+ options,
+ stack.concat([dep])
+ );
+ value = object[dep as keyof T];
+ }
+ return value;
+ });
+ }
+ /**
+ * Return Generator function if the argument is not a function
+ * @param generator - Generator function or value
+ */
+ private _ReturnFunction(
+ generator?: Builder | DefaultValue
+ ): Builder {
+ if (generator instanceof Function) {
+ return generator;
+ } else {
+ return () => generator;
+ }
+ }
+ /**
+ * Return a Entry object with dependencies and builder function
+ * @param generatorOptions - Default value or generator function or dependencies
+ * @param generator - Generator function or value
+ */
+ private _SafeType(
+ generatorOptions?: GeneratorOptions,
+ generator?: Builder
+ ): Entry {
+ let _dependencies: Dependencies | undefined;
+ let _builder: Builder;
+ if (generator === undefined) {
+ if (Array.isArray(generatorOptions)) {
+ throw new Crash('Generator function is required if dependencies are defined', {
+ attributeDependencies: generatorOptions,
+ });
+ }
+ _dependencies = undefined;
+ _builder = this._ReturnFunction(generatorOptions);
+ } else {
+ if (Array.isArray(generatorOptions)) {
+ _dependencies = generatorOptions;
+ _builder = this._ReturnFunction(generator);
+ } else {
+ throw new Crash('Dependencies must be an array', {
+ attributeDependencies: generatorOptions,
+ });
+ }
+ }
+ return { dependencies: _dependencies, builder: _builder };
+ }
+ /**
+ * Generate wrong data, excluding the correct data type
+ * @param type - type of good data
+ */
+ private _wrongData(type: string): any {
+ const _typeof: string[] = [
+ 'undefined',
+ 'boolean',
+ 'number',
+ 'string',
+ 'object',
+ 'symbol',
+ 'bigint',
+ 'function',
+ ].filter(entry => entry !== type);
+ const selected = this._chance.pickone(_typeof);
+ switch (selected) {
+ case 'undefined':
+ return undefined;
+ case 'object':
+ return undefined;
+ case 'boolean':
+ return this._chance.bool();
+ case 'number':
+ if (this._chance.bool()) {
+ return this._chance.floating();
+ } else {
+ return this._chance.natural();
+ }
+ case 'string':
+ return this._chance.string();
+ default:
+ return null;
+ }
+ }
+ /**
+ * Create an object with standard Attributes from a key-value pairs object
+ * @param attributes - object containing attribute override key value pairs
+ */
+ private _convertToAttributes(attributes: { [K in keyof T]?: T[K] }): {
+ [K in keyof T]?: Entry;
+ } {
+ const attrs: { [K in keyof T]?: Entry } = {};
+ for (const attr in attributes) {
+ attrs[attr] = { dependencies: undefined, builder: () => attributes[attr] };
+ }
+ return attrs;
+ }
+}
diff --git a/packages/api/faker/src/index.ts b/packages/api/faker/src/index.ts
new file mode 100644
index 00000000..c9099e36
--- /dev/null
+++ b/packages/api/faker/src/index.ts
@@ -0,0 +1,11 @@
+/**
+ * Copyright 2023 Netin Systems S.L. All rights reserved.
+ * Note: All information contained herein is, and remains the property of Netin Systems S.L. and its
+ * suppliers, if any. The intellectual and technical concepts contained herein are property of
+ * Netin Systems S.L. and its suppliers and may be covered by European and Foreign patents, patents
+ * in process, and are protected by trade secret or copyright.
+ *
+ * Dissemination of this information or the reproduction of this material is strictly forbidden
+ * unless prior written permission is obtained from Netin Systems S.L.
+ */
+export * from './Factory';
diff --git a/packages/api/faker/stryker.conf.js b/packages/api/faker/stryker.conf.js
new file mode 100644
index 00000000..4a5e37e0
--- /dev/null
+++ b/packages/api/faker/stryker.conf.js
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2022 Mytra Control S.L. All rights reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be found in the LICENSE file
+ * or at https://opensource.org/licenses/MIT.
+ */
+ module.exports = require('@mdf.js/repo-config').getStrykerConfig(__dirname);
+
diff --git a/packages/api/faker/tsconfig.build.json b/packages/api/faker/tsconfig.build.json
new file mode 100644
index 00000000..abaefaf4
--- /dev/null
+++ b/packages/api/faker/tsconfig.build.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "declaration": true,
+ "types": ["node"]
+ },
+ "exclude": ["src/**/*.test.ts"],
+ "include": ["src/**/*.ts"]
+}
diff --git a/packages/api/faker/tsconfig.json b/packages/api/faker/tsconfig.json
new file mode 100644
index 00000000..a812543b
--- /dev/null
+++ b/packages/api/faker/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "@mdf.js/repo-config/tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "./dist",
+ "rootDir": "./src",
+ },
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/packages/api/faker/tsconfig.lint.json b/packages/api/faker/tsconfig.lint.json
new file mode 100644
index 00000000..56fd5680
--- /dev/null
+++ b/packages/api/faker/tsconfig.lint.json
@@ -0,0 +1,4 @@
+{
+ "extends": "./tsconfig.json",
+ "include": ["src/**/*.ts"]
+}
diff --git a/packages/api/faker/tsconfig.spec.json b/packages/api/faker/tsconfig.spec.json
new file mode 100644
index 00000000..9d286887
--- /dev/null
+++ b/packages/api/faker/tsconfig.spec.json
@@ -0,0 +1,8 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "module": "commonjs",
+ "types": ["jest", "node"]
+ },
+ "include": ["src/**/*.ts", "jest.config.js"]
+}
diff --git a/packages/api/faker/typedoc.json b/packages/api/faker/typedoc.json
new file mode 100644
index 00000000..7e3e4fa4
--- /dev/null
+++ b/packages/api/faker/typedoc.json
@@ -0,0 +1,33 @@
+{
+ "entryPoints": [
+ "src/index.ts"
+ ],
+ "tsconfig": "./tsconfig.build.json",
+ "entryPointStrategy": "resolve",
+ "exclude": [
+ "**/dist/**",
+ "**/node_modules",
+ "src/**/*.test.ts",
+ "src/**/test/*.*"
+ ],
+ "externalPattern": ["**/node_modules/**"],
+ "excludeExternals": true,
+ "excludePrivate": true,
+ "excludeProtected": true,
+ "excludeInternal": true,
+ "includes": [],
+ "media": "media",
+ "out": "../../../docs/api/faker",
+ "markedOptions": {
+ "gfm": true
+ },
+ "name": "@mdf.js/faker",
+ "includeVersion": true,
+ "disableSources": true,
+ "excludeTags": [],
+ "readme": "README.md",
+ "categorizeByGroup": false,
+ "categoryOrder": [],
+ "cleanOutputDir": true,
+ "gitRevision": "master",
+}
diff --git a/packages/api/middlewares/src/metrics/metrics.ts b/packages/api/middlewares/src/metrics/metrics.ts
index 72e5af0d..66dac05b 100644
--- a/packages/api/middlewares/src/metrics/metrics.ts
+++ b/packages/api/middlewares/src/metrics/metrics.ts
@@ -147,7 +147,7 @@ export class Metrics {
response: Response
): { request: number; response: number } {
const reqHeaderContentLength = request.headers[CONTENT_LENGTH_HEADER]
- ? parseInt(request.headers[CONTENT_LENGTH_HEADER] as string)
+ ? parseInt(request.headers[CONTENT_LENGTH_HEADER])
: 0;
const resHeaderContentLength = response.getHeader(CONTENT_LENGTH_HEADER);
let responseLength: number;
diff --git a/packages/api/openc2-core/src/components/Producer/Producer.ts b/packages/api/openc2-core/src/components/Producer/Producer.ts
index 9eb58292..72e29147 100644
--- a/packages/api/openc2-core/src/components/Producer/Producer.ts
+++ b/packages/api/openc2-core/src/components/Producer/Producer.ts
@@ -227,39 +227,7 @@ export class Producer extends Component {
this.logger.debug(`Timeout for responses to command ${requestId}: ${timeout} ms`);
// *******************************************************************************************
// #region Incoming response handler
- const incomingResponseHandler = (incomingMessage: Control.Message): void => {
- try {
- const message = Checkers.isValidResponseSync(incomingMessage, this.componentId);
- // Stryker disable next-line all
- this.logger.debug(`New message from ${message.from} - ${message.request_id}`);
- if (!Checkers.isResponseToInstance(message, command.from, requestId)) {
- // Stryker disable next-line all
- this.logger.debug(`${message.request_id} is not a response for this instance`);
- return;
- } else if (message.request_id === requestId) {
- this.register.push(message);
- if (message.status >= 200) {
- // Stryker disable next-line all
- this.logger.debug(`Response from: [${message.from}] received`);
- responses.push(message);
- } else {
- // Stryker disable next-line all
- this.logger.debug(`ACK from: [${message.from}] received`);
- if (command.content.args?.response_requested === Control.ResponseType.ACK) {
- responses.push(message);
- }
- }
- }
- } catch (rawError) {
- const error = Crash.from(rawError);
- const processingError = new Crash(
- `Error processing incoming response message from control chanel: ${error.message}`,
- this.componentId,
- { cause: error }
- );
- this.onErrorHandler(processingError);
- }
- };
+ const broadcastResponseHandler = this.getBroadcastResponseHandler(command, responses);
// #endregion
// *******************************************************************************************
// #region On timeout event handler
@@ -268,7 +236,7 @@ export class Producer extends Component {
this.logger.debug(
`Timeout complete for command: ${requestId}, all the responses will be resolved`
);
- this.adapter.off(requestId, incomingResponseHandler);
+ this.adapter.off(requestId, broadcastResponseHandler);
resolve(responses);
};
// #endregion
@@ -280,9 +248,9 @@ export class Producer extends Component {
if (result) {
const directResponses = Array.isArray(result) ? result : [result];
for (const response of directResponses) {
- incomingResponseHandler(response);
+ broadcastResponseHandler(response);
}
- this.adapter.off(requestId, incomingResponseHandler);
+ this.adapter.off(requestId, broadcastResponseHandler);
clearTimeout(timeoutTimer);
resolve(directResponses);
}
@@ -292,7 +260,7 @@ export class Producer extends Component {
// #region On error on publish method
const onPublishError = (rawError: unknown) => {
clearTimeout(timeoutTimer);
- this.adapter.off(requestId, incomingResponseHandler);
+ this.adapter.off(requestId, broadcastResponseHandler);
const error = Crash.from(rawError);
const publishingError = new Crash(
`Error publishing command to control channel: ${error.message}`,
@@ -305,11 +273,49 @@ export class Producer extends Component {
// #endregion
// *******************************************************************************************
// #region Subscription to responses
- this.adapter.on(requestId, incomingResponseHandler);
+ this.adapter.on(requestId, broadcastResponseHandler);
const timeoutTimer = setTimeout(onTimeout, timeout);
this.adapter.publish(command).then(onDirectResponse).catch(onPublishError);
});
}
+ /**
+ * Wait for the response of several consumers during the defined duration in the command
+ * @param command - issued command
+ * @param responses - responses array
+ */
+ private getBroadcastResponseHandler(
+ command: Control.CommandMessage,
+ responses: Control.ResponseMessage[]
+ ): (incomingMessage: Control.Message) => void {
+ const requestId = command.request_id;
+ return (incomingMessage: Control.Message) => {
+ try {
+ const message = Checkers.isValidResponseSync(incomingMessage, this.componentId);
+ // Stryker disable next-line all
+ this.logger.debug(`New message from ${message.from} - ${message.request_id}`);
+ if (!Checkers.isResponseToInstance(message, command.from, requestId)) {
+ // Stryker disable next-line all
+ this.logger.debug(`${message.request_id} is not a response for this instance`);
+ return;
+ } else if (message.request_id === requestId) {
+ this.register.push(message);
+ if (message.status >= 200) {
+ // Stryker disable next-line all
+ this.logger.debug(`Response from: [${message.from}] received`);
+ responses.push(message);
+ } else {
+ // Stryker disable next-line all
+ this.logger.debug(`ACK from: [${message.from}] received`);
+ if (command.content.args?.response_requested === Control.ResponseType.ACK) {
+ responses.push(message);
+ }
+ }
+ }
+ } catch (rawError) {
+ this.onProcessingMessageError(rawError);
+ }
+ };
+ }
/**
* Wait for the response to an issued command from one consumer
* @param command - issued command
@@ -321,10 +327,10 @@ export class Producer extends Component {
const requestId = command.request_id;
const timeout = Accessors.getDelayFromCommandMessage(command);
// Stryker disable next-line all
- this.logger.debug(`Timeout for responses: ${timeout} ms`);
+ this.logger.debug(`Timeout for responses to command ${requestId}: ${timeout} ms`);
// *******************************************************************************************
// #region Incoming response handler
- const incomingResponseHandler = (incomingMessage: Control.Message): void => {
+ const consumerResponseHandler = (incomingMessage: Control.Message): void => {
try {
const message = Checkers.isValidResponseSync(incomingMessage, this.componentId);
// Stryker disable next-line all
@@ -333,42 +339,21 @@ export class Producer extends Component {
// Stryker disable next-line all
this.logger.debug(`${message.request_id} is not a response for this instance`);
} else if (message.request_id === requestId) {
- this.register.push(message);
- if (message.status >= 200 && message.status < 300) {
- clearTimeout(timeoutTimer);
- this.adapter.off(requestId, incomingResponseHandler);
- // Stryker disable next-line all
- this.logger.debug(`Response from: [${message.from}] received - Fulfilled`);
- resolve(message);
- } else if (message.status >= 300) {
- clearTimeout(timeoutTimer);
- this.adapter.off(requestId, incomingResponseHandler);
- // Stryker disable next-line all
- this.logger.warn(`Response from: [${message.from}] received - Not fulfilled`);
- reject(
- new Crash(
- `Command was not fulfilled: [status ${message.status}]`,
- message.request_id
- )
- );
- } else {
- // Stryker disable next-line all
- this.logger.debug(`ACK from: [${message.from}] received`);
- if (command.content.args?.response_requested === Control.ResponseType.ACK) {
+ try {
+ const result = this.handlerMessage(message, command);
+ if (result) {
clearTimeout(timeoutTimer);
- this.adapter.off(requestId, incomingResponseHandler);
- resolve(message);
+ this.adapter.off(requestId, consumerResponseHandler);
+ resolve(result);
}
+ } catch (rawError) {
+ clearTimeout(timeoutTimer);
+ this.adapter.off(requestId, consumerResponseHandler);
+ reject(rawError);
}
}
} catch (rawError) {
- const error = Crash.from(rawError);
- const processingError = new Crash(
- `Error processing incoming response message from control chanel: ${error.message}`,
- this.componentId,
- { cause: error }
- );
- this.onErrorHandler(processingError);
+ this.onProcessingMessageError(rawError);
}
};
// #endregion
@@ -380,7 +365,7 @@ export class Producer extends Component {
requestId
);
this.logger.debug(timeOutError.message);
- this.adapter.off(requestId, incomingResponseHandler);
+ this.adapter.off(requestId, consumerResponseHandler);
reject(timeOutError);
};
// #endregion
@@ -391,7 +376,7 @@ export class Producer extends Component {
) => {
if (Array.isArray(result)) {
clearTimeout(timeoutTimer);
- this.adapter.off(requestId, incomingResponseHandler);
+ this.adapter.off(requestId, consumerResponseHandler);
reject(
new Crash(
`Command to a single destination was resolved with multiple responses: ${result.length}`,
@@ -400,7 +385,7 @@ export class Producer extends Component {
)
);
} else if (result) {
- incomingResponseHandler(result);
+ consumerResponseHandler(result);
}
};
// #endregion
@@ -408,7 +393,7 @@ export class Producer extends Component {
// #region On error on publish method
const onPublishError = (rawError: unknown) => {
clearTimeout(timeoutTimer);
- this.adapter.off(requestId, incomingResponseHandler);
+ this.adapter.off(requestId, consumerResponseHandler);
const error = Crash.from(rawError);
const publishingError = new Crash(
`Error publishing command to control channel: ${error.message}`,
@@ -419,9 +404,44 @@ export class Producer extends Component {
reject(publishingError);
};
// #endregion
- this.adapter.on(requestId, incomingResponseHandler);
+ this.adapter.on(requestId, consumerResponseHandler);
const timeoutTimer = setTimeout(onTimeout, timeout);
this.adapter.publish(command).then(onDirectResponse).catch(onPublishError);
});
}
+ private handlerMessage(
+ message: Control.ResponseMessage,
+ command: Control.CommandMessage
+ ): Control.ResponseMessage | undefined {
+ this.register.push(message);
+ if (message.status >= 200 && message.status < 300) {
+ // Stryker disable next-line all
+ this.logger.debug(`Response from: [${message.from}] received - Fulfilled`);
+ return message;
+ } else if (message.status >= 300) {
+ // Stryker disable next-line all
+ this.logger.warn(`Response from: [${message.from}] received - Not fulfilled`);
+ throw new Crash(`Command was not fulfilled: [status ${message.status}]`, message.request_id);
+ } else {
+ // Stryker disable next-line all
+ this.logger.debug(`ACK from: [${message.from}] received`);
+ if (command.content.args?.response_requested === Control.ResponseType.ACK) {
+ return message;
+ }
+ return undefined;
+ }
+ }
+ /**
+ * Handle errors processing incoming messages
+ * @param rawError - raw error
+ */
+ private readonly onProcessingMessageError = (rawError: unknown) => {
+ const error = Crash.from(rawError);
+ const processingError = new Crash(
+ `Error processing incoming response message from control chanel: ${error.message}`,
+ this.componentId,
+ { cause: error }
+ );
+ this.onErrorHandler(processingError);
+ };
}
diff --git a/packages/api/utils/src/cycle/cycle.ts b/packages/api/utils/src/cycle/cycle.ts
index b819c589..ce5642ec 100644
--- a/packages/api/utils/src/cycle/cycle.ts
+++ b/packages/api/utils/src/cycle/cycle.ts
@@ -40,37 +40,48 @@ export function deCycle(object: any, replacer?: (value: any) => any) {
}
export function retroCycle($: any) {
const px = /^\$(?:\[(?:\d+|"(?:[^\\"\u0000-\u001f]|\\(?:[\\"\/bfnrt]|u[0-9a-zA-Z]{4}))*")\])*$/;
+ function processArray(value: any[]) {
+ value.forEach((item, i) => {
+ if (typeof item === 'object' && item !== null) {
+ const path = item.$ref;
+ if (typeof path === 'string' && px.test(path)) {
+ value[i] = eval(path);
+ } else {
+ rez(item);
+ }
+ }
+ });
+ }
+ function processObject(object: any) {
+ for (const key in object) {
+ if (object.hasOwnProperty(key)) {
+ const item = object[key];
+ if (typeof item === 'object' && item !== null) {
+ const path = item.$ref;
+ if (typeof path === 'string' && px.test(path)) {
+ object[key] = eval(path);
+ } else {
+ rez(item);
+ }
+ }
+ }
+ }
+ }
- (function rez(value) {
+ function rez(value: any) {
if (value && typeof value === 'object') {
if (Array.isArray(value)) {
- value.forEach(function (element, i) {
- if (typeof element === 'object' && element !== null) {
- const path = element.$ref;
- if (typeof path === 'string' && px.test(path)) {
- value[i] = eval(path);
- } else {
- rez(element);
- }
- }
- });
+ processArray(value);
} else {
- Object.keys(value).forEach(function (name) {
- const item = value[name];
- if (typeof item === 'object' && item !== null) {
- const path = item.$ref;
- if (typeof path === 'string' && px.test(path)) {
- value[name] = eval(path);
- } else {
- rez(item);
- }
- }
- });
+ processObject(value);
}
}
- })($);
+ }
+
+ rez($);
return $;
}
+
/**
* Check if a value is valid object
* @param value - The value to be checked
diff --git a/packages/providers/amqp/src/Receiver/Provider.test.ts b/packages/providers/amqp/src/Receiver/Provider.test.ts
index 14c5b7c6..788d4885 100644
--- a/packages/providers/amqp/src/Receiver/Provider.test.ts
+++ b/packages/providers/amqp/src/Receiver/Provider.test.ts
@@ -31,8 +31,6 @@ const DEFAULT_CONFIG: Config = {
},
},
reconnect: 5000,
- rejectUnauthorized: false,
- requestCert: false,
transport: 'tcp',
username: 'consumer',
};
diff --git a/packages/providers/amqp/src/Receiver/config/config.test.ts b/packages/providers/amqp/src/Receiver/config/config.test.ts
index 28c58617..c8c6a4fd 100644
--- a/packages/providers/amqp/src/Receiver/config/config.test.ts
+++ b/packages/providers/amqp/src/Receiver/config/config.test.ts
@@ -28,8 +28,6 @@ describe(`#Config #${CONFIG_PROVIDER_BASE_NAME.toLocaleUpperCase()} Receiver`, (
rcv_settle_mode: 0,
},
reconnect: 5000,
- rejectUnauthorized: false,
- requestCert: false,
transport: 'tcp',
username: 'consumer',
});
diff --git a/packages/providers/amqp/src/Receiver/config/default.ts b/packages/providers/amqp/src/Receiver/config/default.ts
index 04a1f303..91f8bbd2 100644
--- a/packages/providers/amqp/src/Receiver/config/default.ts
+++ b/packages/providers/amqp/src/Receiver/config/default.ts
@@ -19,8 +19,6 @@ const CONFIG_AMQP_RECONNECT = 5000;
const CONFIG_AMQP_INITIAL_RECONNECT_DELAY = 30000;
const CONFIG_AMQP_MAX_RECONNECT_DELAY = 10000;
const CONFIG_AMQP_NON_FATAL_ERRORS = ['amqp:connection:forced'];
-const CONFIG_AMQP_REQUEST_CERT = false;
-const CONFIG_AMQP_REJECT_UNAUTHORIZED = false;
const CONFIG_AMQP_RECEIVER_SETTLE_MODE = 0;
const CONFIG_AMQP_RECEIVER_CREDIT_WINDOW = 0;
const CONFIG_AMQP_RECEIVER_AUTO_ACCEPT = false;
@@ -36,8 +34,6 @@ export const defaultConfig: Config = {
initial_reconnect_delay: CONFIG_AMQP_INITIAL_RECONNECT_DELAY,
max_reconnect_delay: CONFIG_AMQP_MAX_RECONNECT_DELAY,
non_fatal_errors: CONFIG_AMQP_NON_FATAL_ERRORS,
- requestCert: CONFIG_AMQP_REQUEST_CERT,
- rejectUnauthorized: CONFIG_AMQP_REJECT_UNAUTHORIZED,
receiver_options: {
name: CONFIG_ARTIFACT_ID,
rcv_settle_mode: CONFIG_AMQP_RECEIVER_SETTLE_MODE,
diff --git a/packages/providers/amqp/src/Sender/Provider.test.ts b/packages/providers/amqp/src/Sender/Provider.test.ts
index dd6da10a..19af1cf8 100644
--- a/packages/providers/amqp/src/Sender/Provider.test.ts
+++ b/packages/providers/amqp/src/Sender/Provider.test.ts
@@ -26,8 +26,6 @@ const DEFAULT_CONFIG: Config = {
autosettle: true,
},
reconnect: 5000,
- rejectUnauthorized: false,
- requestCert: false,
transport: 'tcp',
username: 'consumer',
};
diff --git a/packages/providers/amqp/src/Sender/config/config.test.ts b/packages/providers/amqp/src/Sender/config/config.test.ts
index 165ab8fd..75e916cf 100644
--- a/packages/providers/amqp/src/Sender/config/config.test.ts
+++ b/packages/providers/amqp/src/Sender/config/config.test.ts
@@ -27,8 +27,6 @@ describe(`#Config #${CONFIG_PROVIDER_BASE_NAME.toLocaleUpperCase()} Sender`, ()
autosettle: true,
},
reconnect: 5000,
- rejectUnauthorized: false,
- requestCert: false,
transport: 'tcp',
username: 'producer',
});
diff --git a/packages/providers/amqp/src/Sender/config/default.ts b/packages/providers/amqp/src/Sender/config/default.ts
index 5d8e9962..fc00c70f 100644
--- a/packages/providers/amqp/src/Sender/config/default.ts
+++ b/packages/providers/amqp/src/Sender/config/default.ts
@@ -19,8 +19,6 @@ const CONFIG_AMQP_RECONNECT = 5000;
const CONFIG_AMQP_INITIAL_RECONNECT_DELAY = 30000;
const CONFIG_AMQP_MAX_RECONNECT_DELAY = 10000;
const CONFIG_AMQP_NON_FATAL_ERRORS = ['amqp:connection:forced'];
-const CONFIG_AMQP_REQUEST_CERT = false;
-const CONFIG_AMQP_REJECT_UNAUTHORIZED = false;
const CONFIG_AMQP_SENDER_SETTLE_MODE = 2;
const CONFIG_AMQP_SENDER_AUTO_SETTLE = true;
const CONFIG_AMQP_SENDER_TARGET = {};
@@ -35,8 +33,6 @@ export const defaultConfig: Config = {
initial_reconnect_delay: CONFIG_AMQP_INITIAL_RECONNECT_DELAY,
max_reconnect_delay: CONFIG_AMQP_MAX_RECONNECT_DELAY,
non_fatal_errors: CONFIG_AMQP_NON_FATAL_ERRORS,
- requestCert: CONFIG_AMQP_REQUEST_CERT,
- rejectUnauthorized: CONFIG_AMQP_REJECT_UNAUTHORIZED,
sender_options: {
name: CONFIG_ARTIFACT_ID,
snd_settle_mode: CONFIG_AMQP_SENDER_SETTLE_MODE,
diff --git a/packages/providers/http-client/src/provider/Port.ts b/packages/providers/http-client/src/provider/Port.ts
index 5a81282a..0f9df7b8 100644
--- a/packages/providers/http-client/src/provider/Port.ts
+++ b/packages/providers/http-client/src/provider/Port.ts
@@ -43,17 +43,14 @@ export class Port extends Layer.Provider.Port {
public async start(): Promise {
// Stryker disable next-line all
this.logger.debug(`Starting HTTP Client port: ${this.uuid}`);
- return;
}
/** Stop the port instance */
public async stop(): Promise {
// Stryker disable next-line all
this.logger.debug(`Stopping HTTP Client port: ${this.uuid}`);
- return;
}
/** Close the port instance */
public async close(): Promise {
await this.stop();
- return;
}
}
diff --git a/packages/providers/http-server/src/config/public/index.html b/packages/providers/http-server/src/config/public/index.html
index 6ed5de32..51d1b158 100644
--- a/packages/providers/http-server/src/config/public/index.html
+++ b/packages/providers/http-server/src/config/public/index.html
@@ -200,7 +200,6 @@ Error CONFIGURING YOUR APP
p.appendChild(s);
})(document.createElement('script'), document.body);
}
- // {{ end }}