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) + + +

+

+ netin +
+

+ +

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 }}