├── .config └── husky │ ├── commit-msg │ ├── pre-commit │ └── prepare-commit-msg ├── .env ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug.yaml │ ├── config.yml │ ├── docs.yaml │ ├── feature.yaml │ └── package.yaml └── workflows │ ├── checks.yml │ ├── publish-npm.yml │ └── tools.yml ├── .gitignore ├── .npmrc ├── .pnp.cjs ├── .pnp.loader.mjs ├── .yarn ├── releases │ └── yarn-remote.mjs └── sdks │ ├── integrations.yml │ └── typescript │ ├── bin │ ├── tsc │ └── tsserver │ ├── lib │ ├── tsc.js │ ├── tsserver.js │ ├── tsserverlibrary.js │ └── typescript.js │ └── package.json ├── .yarnrc.yml ├── LICENSE ├── README.md ├── examples ├── grpc-http-proxy │ ├── CHANGELOG.md │ ├── buf.gen.yaml │ ├── buf.yaml │ ├── package.json │ ├── proto │ │ ├── examples │ │ │ └── echo │ │ │ │ └── v1 │ │ │ │ ├── echo.proto │ │ │ │ └── echo.ts │ │ └── index.ts │ └── src │ │ ├── bootstrap.ts │ │ ├── echo │ │ ├── echo.controller.ts │ │ ├── echo.module.ts │ │ └── index.ts │ │ ├── grpc-http-proxy-app.module.ts │ │ ├── index.ts │ │ ├── proto.d.ts │ │ └── server.options.ts ├── grpc-playground │ ├── CHANGELOG.md │ ├── buf.gen.yaml │ ├── buf.yaml │ ├── package.json │ ├── proto │ │ ├── examples │ │ │ └── playground │ │ │ │ └── v1 │ │ │ │ ├── playground.proto │ │ │ │ └── playground.ts │ │ └── index.ts │ └── src │ │ ├── bootstrap.ts │ │ ├── grpc-playground-app.module.ts │ │ ├── index.ts │ │ ├── playground │ │ ├── index.ts │ │ ├── playground.controller.ts │ │ └── playground.module.ts │ │ ├── proto.d.ts │ │ └── server.options.ts └── grpc-reflection │ ├── CHANGELOG.md │ ├── buf.gen.yaml │ ├── buf.yaml │ ├── package.json │ ├── proto │ ├── examples │ │ └── echo │ │ │ └── v1 │ │ │ ├── echo.proto │ │ │ └── echo.ts │ └── index.ts │ └── src │ ├── bootstrap.ts │ ├── echo │ ├── echo.controller.ts │ ├── echo.module.ts │ └── index.ts │ ├── grpc-reflection-app.module.ts │ ├── index.ts │ ├── proto.d.ts │ └── server.options.ts ├── package.json ├── packages ├── nestjs-batch-queue │ ├── integration │ │ └── test │ │ │ ├── batch-queue.test.ts │ │ │ └── helpers │ │ │ ├── index.ts │ │ │ └── wait-for-consume-count.ts │ ├── package.json │ └── src │ │ ├── batch-queue │ │ ├── batch-queue.interface.ts │ │ ├── batch-queue.test.ts │ │ ├── batch-queue.ts │ │ ├── batch-queue.types.ts │ │ ├── index.ts │ │ └── mutex.ts │ │ ├── check-manager │ │ ├── check-manager.test.ts │ │ ├── check-manager.ts │ │ ├── check-manager.types.ts │ │ └── index.ts │ │ ├── constants │ │ ├── batch-queue.constants.ts │ │ └── index.ts │ │ ├── errors │ │ ├── batch-queue.errors.ts │ │ └── index.ts │ │ ├── index.ts │ │ ├── module │ │ ├── batch-queue-module-options.interface.ts │ │ ├── batch-queue.inject.ts │ │ ├── batch-queue.module.ts │ │ ├── batch-queue.providers.ts │ │ └── index.ts │ │ └── proxy-clases │ │ ├── checker.ts │ │ ├── consumer.ts │ │ ├── index.ts │ │ ├── producer.ts │ │ └── state-handler.ts ├── nestjs-connectrpc-errors │ ├── CHANGELOG.md │ ├── buf.gen.yaml │ ├── integration │ │ ├── connectrpc-errors.test.ts │ │ ├── gen │ │ │ ├── interfaces │ │ │ │ └── test_pb.ts │ │ │ ├── test_connect.ts │ │ │ └── test_pb.ts │ │ ├── proto │ │ │ └── test.proto │ │ └── src │ │ │ ├── connectrpc-errors-integration.module.ts │ │ │ ├── index.ts │ │ │ ├── test.controller.ts │ │ │ └── test.payload.ts │ ├── package.json │ └── src │ │ ├── exception-factories │ │ ├── assertion.exception-factory.ts │ │ ├── domain.exception-factory.ts │ │ ├── guard.exception-factory.ts │ │ ├── index.ts │ │ └── validation.exception-factory.ts │ │ ├── exception-filters │ │ ├── connectrpc.exception-filter.ts │ │ └── index.ts │ │ └── index.ts ├── nestjs-connectrpc │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ └── src │ │ ├── connectrpc.constants.ts │ │ ├── connectrpc.decorators.ts │ │ ├── connectrpc.interfaces.ts │ │ ├── connectrpc.server.ts │ │ ├── connectrpc.strategy.ts │ │ ├── custom-metadata.storage.ts │ │ ├── index.ts │ │ └── utils │ │ ├── async.utils.ts │ │ └── router.utils.ts ├── nestjs-cqrs-kafka-events │ ├── CHANGELOG.md │ ├── package.json │ └── src │ │ ├── index.ts │ │ ├── messaging │ │ ├── index.ts │ │ ├── kafka.publisher.ts │ │ └── kafka.subscriber.ts │ │ └── module │ │ ├── cqrs-kafka-events.module.constants.ts │ │ ├── cqrs-kafka-events.module.interfaces.ts │ │ ├── cqrs-kafka-events.module.ts │ │ └── index.ts ├── nestjs-cqrs │ ├── CHANGELOG.md │ ├── package.json │ └── src │ │ ├── cqrs.module.ts │ │ └── index.ts ├── nestjs-dataloader │ ├── README.md │ ├── package.json │ └── src │ │ ├── constants.ts │ │ ├── decorators │ │ ├── index.ts │ │ ├── loader.decorator.ts │ │ └── order-result-by-key.decorator.ts │ │ ├── index.ts │ │ ├── interceptors │ │ ├── data-loader.interceptor.ts │ │ └── index.ts │ │ └── interfaces │ │ ├── index.ts │ │ └── nest-dataloader.interfaces.ts ├── nestjs-external-renderer │ ├── CHANGELOG.md │ ├── integration │ │ ├── src │ │ │ ├── exec.controller.ts │ │ │ ├── external-renderer-integration.module.ts │ │ │ ├── index.ts │ │ │ └── render.controller.ts │ │ └── test │ │ │ └── render.test.ts │ ├── package.json │ └── src │ │ ├── config │ │ ├── external-renderer-env.config.ts │ │ └── index.ts │ │ ├── index.ts │ │ ├── module │ │ ├── external-renderer-module-options.interface.ts │ │ ├── external-renderer.constants.ts │ │ ├── external-renderer.module.test.ts │ │ ├── external-renderer.module.ts │ │ ├── external-renderer.providers.ts │ │ └── index.ts │ │ └── renderer │ │ ├── express-external-renderer.view.test.ts │ │ ├── express-external-renderer.view.ts │ │ ├── external.renderer.ts │ │ └── index.ts ├── nestjs-gateway │ ├── CHANGELOG.md │ ├── integration │ │ ├── src │ │ │ ├── gateway-integration.module.ts │ │ │ ├── index.ts │ │ │ ├── movies.controller.ts │ │ │ └── service.proto │ │ └── test │ │ │ └── gateway.test.ts │ ├── package.json │ └── src │ │ ├── enums │ │ ├── gateway-source-type.enum.ts │ │ └── index.ts │ │ ├── index.ts │ │ ├── mesh │ │ ├── format.error.ts │ │ ├── graphql-mesh.config.ts │ │ ├── graphql-mesh.handler.ts │ │ ├── graphql-mesh.logger.ts │ │ ├── graphql-mesh.schema-dumper.ts │ │ ├── graphql.mesh.ts │ │ ├── handlers │ │ │ └── grpc │ │ │ │ ├── grpc.handler.ts │ │ │ │ ├── patch-long-js.ts │ │ │ │ ├── scalars.ts │ │ │ │ └── utils.ts │ │ └── index.ts │ │ └── module │ │ ├── gateway-module-options.interface.ts │ │ ├── gateway.constants.ts │ │ ├── gateway.module.ts │ │ ├── gateway.providers.ts │ │ └── index.ts ├── nestjs-gcs-client │ ├── CHANGELOG.md │ ├── package.json │ └── src │ │ ├── index.ts │ │ └── module │ │ ├── gcs-client.config-factory.ts │ │ ├── gcs-client.factory.ts │ │ ├── gcs-client.module.constants.ts │ │ ├── gcs-client.module.interfaces.ts │ │ ├── gcs-client.module.ts │ │ └── index.ts ├── nestjs-graphql-redis-subscriptions │ ├── package.json │ └── src │ │ ├── index.ts │ │ └── module │ │ ├── graphql-redis-subscriptions.module.interfaces.ts │ │ ├── graphql-redis-subscriptions.module.ts │ │ └── index.ts ├── nestjs-grpc-errors │ ├── CHANGELOG.md │ ├── integration │ │ ├── src │ │ │ ├── grpc-errors-integration.module.ts │ │ │ ├── index.ts │ │ │ ├── proto.options.ts │ │ │ ├── test.controller.ts │ │ │ ├── test.dto.ts │ │ │ └── test.proto │ │ └── test │ │ │ └── grpc-errors.test.ts │ ├── package.json │ └── src │ │ ├── exception-factories │ │ ├── assertion.exception-factory.ts │ │ ├── grpc-validation.exception-factory.ts │ │ ├── index.ts │ │ ├── internal-server.exception-factory.ts │ │ └── not-found.exception-factory.ts │ │ ├── exception-filters │ │ ├── grpc.exception-filter.ts │ │ └── index.ts │ │ ├── index.ts │ │ └── pipes │ │ ├── grpc-validation.pipe.ts │ │ └── index.ts ├── nestjs-grpc-http-proxy │ ├── integration │ │ ├── src │ │ │ ├── grpc-http-proxy-integration.module.ts │ │ │ ├── index.ts │ │ │ ├── nope.authenticator.ts │ │ │ ├── proto.options.ts │ │ │ ├── test.controller.ts │ │ │ └── test.proto │ │ └── test │ │ │ └── grpc-http-proxy.test.ts │ ├── package.json │ └── src │ │ ├── authenticators │ │ ├── authentication.service.ts │ │ ├── authenticator.interface.ts │ │ ├── header.authenticator.ts │ │ ├── index.ts │ │ └── private-key.authenticator.ts │ │ ├── controllers │ │ ├── grpc-http-proxy.controller.ts │ │ └── index.ts │ │ ├── index.ts │ │ ├── module │ │ ├── grpc-http-proxy-module-options.interface.ts │ │ ├── grpc-http-proxy.constants.ts │ │ ├── grpc-http-proxy.module.ts │ │ ├── grpc-http-proxy.providers.ts │ │ └── index.ts │ │ └── proto │ │ ├── index.ts │ │ ├── proto.client.ts │ │ └── proto.registry.ts ├── nestjs-grpc-identity │ ├── CHANGELOG.md │ ├── integration │ │ ├── grpc-identity.test.ts │ │ └── src │ │ │ ├── .jwks.json │ │ │ ├── .jwks.pem │ │ │ ├── grpc-identity-integration.module.ts │ │ │ ├── index.ts │ │ │ ├── proto.options.ts │ │ │ ├── test.controller.ts │ │ │ └── test.proto │ ├── package.json │ └── src │ │ ├── config │ │ ├── grpc-identity-env.config.ts │ │ └── index.ts │ │ ├── decorators │ │ ├── index.ts │ │ └── subject.decorator.ts │ │ ├── guards │ │ ├── grpc-jwt-identity.guard.ts │ │ └── index.ts │ │ ├── index.ts │ │ ├── jwt │ │ ├── index.ts │ │ └── jwt.verifier.ts │ │ └── module │ │ ├── grpc-identity-module.interface.ts │ │ ├── grpc-identity.constants.ts │ │ ├── grpc-identity.module.ts │ │ ├── grpc-identity.providers.ts │ │ └── index.ts ├── nestjs-grpc-keto │ ├── CHANGELOG.md │ ├── README.md │ ├── integration │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── keto-integration.controller.ts │ │ │ └── keto-integration.module.ts │ │ └── test │ │ │ ├── client-read.test.ts │ │ │ ├── keto.yml │ │ │ ├── namespaces.keto.ts │ │ │ ├── relationships.json │ │ │ └── test.constants.ts │ ├── package.json │ └── src │ │ ├── decorators │ │ ├── get-guarding-relation.helper.ts │ │ ├── guarded-by-keto.constants.ts │ │ ├── guarded-by-keto.decorator.ts │ │ ├── guarded-by-keto.interfaces.ts │ │ └── index.ts │ │ ├── exceptions │ │ ├── exception-message.constants.ts │ │ ├── general.exception.ts │ │ ├── index.ts │ │ └── relation-tuple-invalid.exception.ts │ │ ├── guard │ │ ├── index.ts │ │ └── keto.guard.ts │ │ ├── index.ts │ │ ├── module │ │ ├── index.ts │ │ ├── keto-module.interfaces.ts │ │ ├── keto.constants.ts │ │ ├── keto.module.ts │ │ └── keto.providers.ts │ │ ├── services │ │ ├── index.ts │ │ ├── keto-check-client.service.ts │ │ ├── keto-read-client.service.ts │ │ ├── keto-write-client.service.ts │ │ └── keto-write-native-client.service.ts │ │ └── utils │ │ ├── index.ts │ │ └── relation-tuple-converter.ts ├── nestjs-grpc-playground │ ├── CHANGELOG.md │ ├── integration │ │ ├── src │ │ │ ├── grpc-playground-integration.module.ts │ │ │ └── index.ts │ │ └── test │ │ │ └── grpc-playground.test.ts │ ├── package.json │ └── src │ │ ├── controllers │ │ ├── grpc-playground.controller.ts │ │ └── index.ts │ │ ├── index.ts │ │ └── module │ │ ├── grpc-playground-module-options.interface.ts │ │ ├── grpc-playground.constants.ts │ │ ├── grpc-playground.module.ts │ │ └── index.ts ├── nestjs-grpc-reflection │ ├── CHANGELOG.md │ ├── buf.gen.yaml │ ├── buf.yaml │ ├── integration │ │ ├── src │ │ │ ├── grpc-reflection-integration.module.ts │ │ │ ├── index.ts │ │ │ ├── proto.options.ts │ │ │ ├── test.proto │ │ │ ├── test1_service.proto │ │ │ └── test2_service.proto │ │ └── test │ │ │ └── grpc-reflection.test.ts │ ├── package.json │ ├── proto │ │ ├── grpc │ │ │ └── reflection │ │ │ │ └── v1 │ │ │ │ └── reflection.proto │ │ ├── index.cjs │ │ └── index.d.ts │ └── src │ │ ├── controllers │ │ ├── grpc-reflection.controller.ts │ │ └── index.ts │ │ ├── grpc │ │ ├── grpc-services.registry.ts │ │ ├── grpc.reflector.ts │ │ ├── index.ts │ │ └── reflection │ │ │ └── v1 │ │ │ └── reflection.ts │ │ ├── index.ts │ │ └── module │ │ ├── grpc-reflection-module-options.interface.ts │ │ ├── grpc-reflection.constants.ts │ │ ├── grpc-reflection.module.ts │ │ ├── grpc-reflection.providers.ts │ │ └── index.ts ├── nestjs-hydra │ ├── package.json │ └── src │ │ ├── client │ │ └── index.ts │ │ ├── config │ │ ├── hydra-env.config.ts │ │ └── index.ts │ │ ├── index.ts │ │ ├── module │ │ ├── hydra-module-options.interface.ts │ │ ├── hydra.constants.ts │ │ ├── hydra.module.test.ts │ │ ├── hydra.module.ts │ │ ├── hydra.providers.ts │ │ ├── hydra.utils.ts │ │ └── index.ts │ │ └── utils │ │ ├── index.ts │ │ └── state.utils.ts ├── nestjs-kafka │ ├── package.json │ └── src │ │ ├── index.ts │ │ ├── logger │ │ ├── index.ts │ │ └── kafka-log.creator.ts │ │ └── module │ │ ├── index.ts │ │ ├── kafka.config-factory.ts │ │ ├── kafka.factory.ts │ │ ├── kafka.module.constants.ts │ │ └── kafka.module.ts ├── nestjs-keto │ ├── integration │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── keto-integration.controller.ts │ │ │ └── keto-integration.module.ts │ │ └── test │ │ │ ├── client-read.test.ts │ │ │ ├── keto.yml │ │ │ ├── namespaces.keto.ts │ │ │ ├── relationships.json │ │ │ └── test.constants.ts │ ├── package.json │ └── src │ │ ├── decorators │ │ ├── get-guarding-relation.helper.ts │ │ ├── guarded-by-keto.constants.ts │ │ ├── guarded-by-keto.decorator.ts │ │ ├── guarded-by-keto.interfaces.ts │ │ └── index.ts │ │ ├── exceptions │ │ ├── exception-message.constants.ts │ │ ├── general.exception.ts │ │ ├── index.ts │ │ └── relation-tuple-invalid.exception.ts │ │ ├── guards │ │ ├── index.ts │ │ └── keto.guard.ts │ │ ├── index.ts │ │ ├── module │ │ ├── index.ts │ │ ├── keto-module.interfaces.ts │ │ ├── keto.constants.ts │ │ ├── keto.module.test.ts │ │ ├── keto.module.ts │ │ └── keto.providers.ts │ │ ├── services │ │ ├── index.ts │ │ ├── keto-configuration.service.ts │ │ ├── keto-permissions.service.ts │ │ ├── keto-read-client.service.ts │ │ ├── keto-relations.service.ts │ │ └── keto-write-client.service.ts │ │ └── utils │ │ ├── index.ts │ │ ├── relation-tuple-converter.test.ts │ │ └── relation-tuple-converter.ts ├── nestjs-kratos │ ├── integration │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── kratos-integration.module.ts │ │ │ ├── redirect.controller.ts │ │ │ ├── self-service.controller.ts │ │ │ └── session.controller.ts │ │ └── test │ │ │ ├── flow-redirection.test.ts │ │ │ └── flow-session.test.ts │ ├── package.json │ └── src │ │ ├── client │ │ ├── index.ts │ │ ├── kratos-admin.api.ts │ │ └── kratos-public.api.ts │ │ ├── config │ │ ├── index.ts │ │ └── kratos-env.config.ts │ │ ├── decorators │ │ ├── flow.decorator.ts │ │ ├── index.ts │ │ └── whoami.decorator.ts │ │ ├── exceptions │ │ ├── index.ts │ │ ├── kratos-flow-required.exception.ts │ │ └── kratos-redirect-required.exception.ts │ │ ├── filters │ │ ├── index.ts │ │ ├── kratos-exception.filter.test.ts │ │ └── kratos-expection.filter.ts │ │ ├── index.ts │ │ ├── interceptors │ │ ├── index.ts │ │ ├── kratos-redirect.interceptor.test.ts │ │ └── kratos-redirect.interceptor.ts │ │ ├── module │ │ ├── index.ts │ │ ├── kratos-module-options.interface.ts │ │ ├── kratos.constants.ts │ │ ├── kratos.module.test.ts │ │ ├── kratos.module.ts │ │ ├── kratos.providers.ts │ │ └── kratos.utils.ts │ │ ├── pipes │ │ ├── index.ts │ │ └── whoami.pipe.ts │ │ ├── urls │ │ ├── index.ts │ │ └── kratos-browser.urls.ts │ │ └── utils │ │ ├── index.ts │ │ └── method-config.util.ts ├── nestjs-logger │ ├── package.json │ └── src │ │ ├── index.ts │ │ └── logger │ │ ├── index.ts │ │ └── nest.logger.ts ├── nestjs-microservices-registry │ ├── CHANGELOG.md │ ├── package.json │ └── src │ │ ├── index.ts │ │ ├── module │ │ ├── index.ts │ │ └── microservices-registry.module.ts │ │ └── registry │ │ ├── index.ts │ │ └── microservices.registry.ts ├── nestjs-mikro-orm-config │ ├── CHANGELOG.md │ ├── package.json │ └── src │ │ ├── index.ts │ │ └── module │ │ ├── index.ts │ │ ├── mikro-orm-config.module.constants.ts │ │ ├── mikro-orm-config.module.interfaces.ts │ │ ├── mikro-orm-config.module.ts │ │ ├── mikro-orm.config-builder.ts │ │ └── mikro-orm.config.ts ├── nestjs-mikro-orm-request-context │ ├── CHANGELOG.md │ ├── package.json │ └── src │ │ ├── index.ts │ │ ├── interceptors │ │ ├── index.ts │ │ └── mikro-orm-request-context.interceptor.ts │ │ └── module │ │ ├── index.ts │ │ └── mikro-orm-request-context.module.ts ├── nestjs-proto-types │ ├── CHANGELOG.md │ ├── package.json │ └── src │ │ └── index.ts ├── nestjs-redis │ ├── package.json │ └── src │ │ ├── index.ts │ │ └── module │ │ ├── index.ts │ │ ├── redis.config-factory.ts │ │ ├── redis.factory.ts │ │ ├── redis.module.constants.ts │ │ └── redis.module.ts ├── nestjs-s3-client │ ├── CHANGELOG.md │ ├── package.json │ └── src │ │ ├── index.ts │ │ └── module │ │ ├── index.ts │ │ ├── s3-client.config-factory.ts │ │ ├── s3-client.factory.ts │ │ ├── s3-client.module.constants.ts │ │ ├── s3-client.module.interfaces.ts │ │ └── s3-client.module.ts ├── nestjs-signed-url │ ├── CHANGELOG.md │ ├── package.json │ └── src │ │ ├── __tests__ │ │ └── generate-url.test.ts │ │ ├── index.ts │ │ ├── module.ts │ │ ├── services │ │ ├── index.ts │ │ └── signed-url.service.ts │ │ └── storage │ │ ├── abstract.storage.ts │ │ ├── constants.ts │ │ ├── gcs.storage.ts │ │ ├── index.ts │ │ └── storage.interfaces.ts ├── nestjs-typeorm-seeding │ ├── package.json │ └── src │ │ ├── index.ts │ │ └── module │ │ ├── index.ts │ │ ├── typeorm-seeding.module.test.ts │ │ └── typeorm-seeding.module.ts ├── nestjs-typesense-typeorm │ ├── integration │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── test.entity.ts │ │ │ └── typesense-typeorm-integration.module.ts │ │ └── typesense-typeorm.test.ts │ ├── package.json │ └── src │ │ ├── index.ts │ │ ├── module │ │ ├── index.ts │ │ ├── typesense-typeorm-module.interface.ts │ │ ├── typesense-typeorm.constants.ts │ │ ├── typesense-typeorm.module.ts │ │ └── typesense-typeorm.providers.ts │ │ ├── typeorm │ │ ├── index.ts │ │ └── typeorm-listeners.builder.ts │ │ └── typesense │ │ ├── entity-to-document.mapper.ts │ │ └── index.ts ├── nestjs-typesense │ ├── package.json │ └── src │ │ ├── collections │ │ ├── index.ts │ │ └── typesense-colletctions.creator.ts │ │ ├── decorators │ │ ├── field.decorator.test.ts │ │ ├── field.decorator.ts │ │ ├── index.ts │ │ └── schema.decorator.ts │ │ ├── index.ts │ │ ├── metadata │ │ ├── index.ts │ │ ├── schema.metadata.ts │ │ ├── typesense.metadata-accessor.ts │ │ ├── typesense.metadata-explorer.test.ts │ │ ├── typesense.metadata-explorer.ts │ │ └── typesense.metadata-registry.ts │ │ └── module │ │ ├── index.ts │ │ ├── typesense-module.interface.ts │ │ ├── typesense.constants.ts │ │ ├── typesense.module.test.ts │ │ ├── typesense.module.ts │ │ └── typesense.providers.ts └── nestjs-validation │ ├── package.json │ └── src │ ├── errors │ ├── index.ts │ └── validation.error.ts │ ├── index.ts │ ├── module │ ├── index.ts │ └── validation.module.ts │ └── validator │ ├── index.ts │ └── validator.ts ├── project.types.d.ts ├── tsconfig.json └── yarn.lock /.config/husky/commit-msg: -------------------------------------------------------------------------------- 1 | yarn commit message lint -------------------------------------------------------------------------------- /.config/husky/pre-commit: -------------------------------------------------------------------------------- 1 | yarn commit staged -------------------------------------------------------------------------------- /.config/husky/prepare-commit-msg: -------------------------------------------------------------------------------- 1 | yarn commit message $@ -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | NODE_OPTIONS="--experimental-vm-modules" 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | # github: [torinasakura] 4 | custom: ['https://www.tinkoff.ru/cf/ANRIiFuP8ID'] 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Конвенция 4 | url: https://github.com/atls/convention 5 | about: О наших релизах 6 | - name: Telegram 7 | url: https://t.me/atls 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/package.yaml: -------------------------------------------------------------------------------- 1 | name: Package 2 | description: Создание пакета 3 | title: '[Package] ' 4 | type: Package 5 | assignees: 6 | - TorinAsakura 7 | body: 8 | - type: input 9 | id: package-name 10 | attributes: 11 | label: Название пакета 12 | validations: 13 | required: true 14 | 15 | - type: textarea 16 | id: specs 17 | attributes: 18 | label: Для чего нужен пакет? 19 | placeholder: Описание фич пакета, модулей 20 | validations: 21 | required: true 22 | 23 | - type: textarea 24 | id: how-to 25 | attributes: 26 | label: Пример использования 27 | validations: 28 | required: true 29 | 30 | - type: input 31 | id: materials 32 | attributes: 33 | label: Материалы 34 | placeholder: Ссылка на репу, статью 35 | 36 | projects: ['atls/11'] -------------------------------------------------------------------------------- /.github/workflows/checks.yml: -------------------------------------------------------------------------------- 1 | name: Checks 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | check: 8 | name: Checks 9 | uses: atls/shared/.github/workflows/checks.yaml@master 10 | permissions: write-all 11 | with: 12 | node-version: '22' 13 | -------------------------------------------------------------------------------- /.github/workflows/publish-npm.yml: -------------------------------------------------------------------------------- 1 | name: Publish to registry 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - closed 7 | branches: 8 | - master 9 | paths-ignore: 10 | - '.github/**' 11 | 12 | jobs: 13 | publish: 14 | if: github.event.pull_request.merged == true 15 | uses: atls/shared/.github/workflows/publish.yaml@master 16 | permissions: write-all 17 | with: 18 | appId: ${{ vars.ATLANTIS_SUPER_BOT_APP_ID }} 19 | secrets: 20 | appPrivateKey: ${{ secrets.ATLANTIS_SUPER_BOT_PRIVATE_KEY }} 21 | npmAuthToken: ${{ secrets.NPM_TOKEN }} 22 | -------------------------------------------------------------------------------- /.github/workflows/tools.yml: -------------------------------------------------------------------------------- 1 | name: Update tools 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | update-tools: 8 | name: Update tools 9 | uses: atls/shared/.github/workflows/tools.yaml@master 10 | permissions: write-all 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-error.log 6 | 7 | # Runtime data 8 | pids 9 | *.pid 10 | *.seed 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # node-waf configuration 19 | .lock-wscript 20 | 21 | # Compiled binary addons (http://nodejs.org/api/addons.html) 22 | build/Release 23 | 24 | # Dependency directory 25 | node_modules 26 | .yarn-cache 27 | 28 | # Optional npm cache directory 29 | .npm 30 | 31 | # Optional REPL history 32 | .node_repl_history 33 | 34 | # MacOS temporary files 35 | .DS_Store 36 | 37 | # This is the Yarn build state; it's local to each clone 38 | /.yarn/build-state.yml 39 | 40 | # This is the Yarn install state cache, it can be rebuilt anytime 41 | /.yarn/install-state.gz 42 | 43 | # IDE system files & modules 44 | dist/ 45 | *.iml 46 | *.idea 47 | 48 | # next.js output 49 | .next 50 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | @torinasakura:registry=https://npm.pkg.github.com 2 | //npm.pkg.github.com/:_authToken=ghs_M1zHD5xr7sojWWBym6dcItCsAIhMNZ2qC3xH 3 | @torinasakura:registry=https://npm.pkg.github.com 4 | //npm.pkg.github.com/:_authToken=ghs_jzCd31ePmFhBD0eF0nndKiF2pp9Y0l4K3b70 5 | @torinasakura:registry=https://npm.pkg.github.com 6 | //npm.pkg.github.com/:_authToken=ghs_CZgzijdT7QwSgBcpZhfdbmP7D9Kv5e1zNePa 7 | @torinasakura:registry=https://npm.pkg.github.com 8 | //npm.pkg.github.com/:_authToken=ghs_acL4MBwPL6z6B9NZ1EAs8FNb6CYHaR32179R 9 | @torinasakura:registry=https://npm.pkg.github.com 10 | //npm.pkg.github.com/:_authToken=ghs_2PPXl1akeXIyyDS44cctP1dBsndwUt2Vxljk 11 | @torinasakura:registry=https://npm.pkg.github.com 12 | //npm.pkg.github.com/:_authToken=ghs_dDw6l2v22Q5BAApsC6rz6iSuZc20RH1GRtv7 13 | -------------------------------------------------------------------------------- /.yarn/sdks/integrations.yml: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by @yarnpkg/sdks. 2 | # Manual changes might be lost! 3 | 4 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/bin/tsc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, register} = require(`module`); 5 | const {resolve} = require(`path`); 6 | const {pathToFileURL} = require(`url`); 7 | 8 | const relPnpApiPath = "../../../../.pnp.cjs"; 9 | 10 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 11 | const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); 12 | const absRequire = createRequire(absPnpApiPath); 13 | 14 | const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); 15 | const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); 16 | 17 | if (existsSync(absPnpApiPath)) { 18 | if (!process.versions.pnp) { 19 | // Setup the environment to be able to require typescript/bin/tsc 20 | require(absPnpApiPath).setup(); 21 | if (isPnpLoaderEnabled && register) { 22 | register(pathToFileURL(absPnpLoaderPath)); 23 | } 24 | } 25 | } 26 | 27 | const wrapWithUserWrapper = existsSync(absUserWrapperPath) 28 | ? exports => absRequire(absUserWrapperPath)(exports) 29 | : exports => exports; 30 | 31 | // Defer to the real typescript/bin/tsc your application uses 32 | module.exports = wrapWithUserWrapper(absRequire(`typescript/bin/tsc`)); 33 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/bin/tsserver: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, register} = require(`module`); 5 | const {resolve} = require(`path`); 6 | const {pathToFileURL} = require(`url`); 7 | 8 | const relPnpApiPath = "../../../../.pnp.cjs"; 9 | 10 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 11 | const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); 12 | const absRequire = createRequire(absPnpApiPath); 13 | 14 | const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); 15 | const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); 16 | 17 | if (existsSync(absPnpApiPath)) { 18 | if (!process.versions.pnp) { 19 | // Setup the environment to be able to require typescript/bin/tsserver 20 | require(absPnpApiPath).setup(); 21 | if (isPnpLoaderEnabled && register) { 22 | register(pathToFileURL(absPnpLoaderPath)); 23 | } 24 | } 25 | } 26 | 27 | const wrapWithUserWrapper = existsSync(absUserWrapperPath) 28 | ? exports => absRequire(absUserWrapperPath)(exports) 29 | : exports => exports; 30 | 31 | // Defer to the real typescript/bin/tsserver your application uses 32 | module.exports = wrapWithUserWrapper(absRequire(`typescript/bin/tsserver`)); 33 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/lib/tsc.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, register} = require(`module`); 5 | const {resolve} = require(`path`); 6 | const {pathToFileURL} = require(`url`); 7 | 8 | const relPnpApiPath = "../../../../.pnp.cjs"; 9 | 10 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 11 | const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); 12 | const absRequire = createRequire(absPnpApiPath); 13 | 14 | const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); 15 | const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); 16 | 17 | if (existsSync(absPnpApiPath)) { 18 | if (!process.versions.pnp) { 19 | // Setup the environment to be able to require typescript/lib/tsc.js 20 | require(absPnpApiPath).setup(); 21 | if (isPnpLoaderEnabled && register) { 22 | register(pathToFileURL(absPnpLoaderPath)); 23 | } 24 | } 25 | } 26 | 27 | const wrapWithUserWrapper = existsSync(absUserWrapperPath) 28 | ? exports => absRequire(absUserWrapperPath)(exports) 29 | : exports => exports; 30 | 31 | // Defer to the real typescript/lib/tsc.js your application uses 32 | module.exports = wrapWithUserWrapper(absRequire(`typescript/lib/tsc.js`)); 33 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/lib/typescript.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const {existsSync} = require(`fs`); 4 | const {createRequire, register} = require(`module`); 5 | const {resolve} = require(`path`); 6 | const {pathToFileURL} = require(`url`); 7 | 8 | const relPnpApiPath = "../../../../.pnp.cjs"; 9 | 10 | const absPnpApiPath = resolve(__dirname, relPnpApiPath); 11 | const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`); 12 | const absRequire = createRequire(absPnpApiPath); 13 | 14 | const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`); 15 | const isPnpLoaderEnabled = existsSync(absPnpLoaderPath); 16 | 17 | if (existsSync(absPnpApiPath)) { 18 | if (!process.versions.pnp) { 19 | // Setup the environment to be able to require typescript 20 | require(absPnpApiPath).setup(); 21 | if (isPnpLoaderEnabled && register) { 22 | register(pathToFileURL(absPnpLoaderPath)); 23 | } 24 | } 25 | } 26 | 27 | const wrapWithUserWrapper = existsSync(absUserWrapperPath) 28 | ? exports => absRequire(absUserWrapperPath)(exports) 29 | : exports => exports; 30 | 31 | // Defer to the real typescript your application uses 32 | module.exports = wrapWithUserWrapper(absRequire(`typescript`)); 33 | -------------------------------------------------------------------------------- /.yarn/sdks/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript", 3 | "version": "5.4.2-sdk", 4 | "main": "./lib/typescript.js", 5 | "type": "commonjs", 6 | "bin": { 7 | "tsc": "./bin/tsc", 8 | "tsserver": "./bin/tsserver" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | defaultSemverRangePrefix: '' 2 | 3 | enableGlobalCache: true 4 | 5 | globalFolder: ../.yarn/berry 6 | 7 | packageExtensions: 8 | '@nestjs/testing@*': 9 | dependencies: 10 | '@nestjs/platform-express': '*' 11 | 12 | pnpEnableEsmLoader: true 13 | 14 | preferReuse: true 15 | 16 | yarnPath: .yarn/releases/yarn-remote.mjs 17 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1beta1 2 | 3 | plugins: 4 | - name: ts_proto 5 | out: proto 6 | opt: ts_proto_out=proto,nestJs=true,addGrpcMetadata=true,esModuleInterop=true,useOptionals=true 7 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1beta1 2 | 3 | build: 4 | roots: 5 | - proto 6 | 7 | lint: 8 | use: 9 | - DEFAULT 10 | ignore: 11 | - grpc 12 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/grpc-http-proxy", 3 | "version": "0.0.1", 4 | "private": true, 5 | "license": "BSD 3-Clause", 6 | "type": "module", 7 | "scripts": { 8 | "dev": "yarn service dev", 9 | "proto:generate": "buf generate", 10 | "proto:lint": "buf lint" 11 | }, 12 | "dependencies": { 13 | "@atls/nestjs-grpc-http-proxy": "workspace:*", 14 | "@atls/nestjs-grpc-reflection": "workspace:*", 15 | "@grpc/grpc-js": "1.11.2", 16 | "@grpc/proto-loader": "0.7.13", 17 | "@nestjs/common": "10.4.1", 18 | "@nestjs/core": "10.4.1", 19 | "@nestjs/microservices": "10.4.1", 20 | "@nestjs/testing": "10.4.1", 21 | "@types/long": "4.0.2", 22 | "google-protobuf": "3.21.4", 23 | "long": "4.0.0", 24 | "protobufjs": "7.4.0", 25 | "reflect-metadata": "0.2.2", 26 | "rxjs": "7.8.1" 27 | }, 28 | "externalDependencies": { 29 | "@nestjs/common/utils/load-package.util": "*" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/proto/examples/echo/v1/echo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package examples.echo.v1; 4 | 5 | service EchoService { 6 | rpc Echo (EchoRequest) returns (EchoResponse); 7 | } 8 | 9 | message EchoRequest { 10 | bool ping = 1; 11 | } 12 | 13 | message EchoResponse { 14 | bool pong = 1; 15 | } 16 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/proto/index.ts: -------------------------------------------------------------------------------- 1 | export * from './examples/echo/v1/echo.js' 2 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core' 2 | 3 | import { GrpcHttpProxyAppModule } from './grpc-http-proxy-app.module.js' 4 | import { serverOptions } from './server.options.js' 5 | 6 | // eslint-disable-next-line @next/next/no-assign-module-variable 7 | declare const module: { 8 | hot?: { 9 | accept: () => void 10 | dispose: (callback: () => Promise) => void 11 | } 12 | } 13 | 14 | const bootstrap = async (): Promise => { 15 | const app = await NestFactory.create(GrpcHttpProxyAppModule) 16 | 17 | app.connectMicroservice(serverOptions) 18 | 19 | app.enableShutdownHooks() 20 | app.enableCors() 21 | 22 | await app.startAllMicroservices() 23 | await app.listen(3000) 24 | 25 | if (module.hot) { 26 | module.hot.accept() 27 | module.hot.dispose(async () => { 28 | await app.close() 29 | }) 30 | } 31 | } 32 | 33 | bootstrap() 34 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/src/echo/echo.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller } from '@nestjs/common' 2 | import { GrpcMethod } from '@nestjs/microservices' 3 | 4 | import { EchoRequest } from '../../proto/index.js' 5 | import { EchoResponse } from '../../proto/index.js' 6 | 7 | @Controller() 8 | export class EchoController { 9 | @GrpcMethod('EchoService', 'Echo') 10 | echo(request: EchoRequest): EchoResponse { 11 | return { 12 | pong: request.ping, 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/src/echo/echo.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { EchoController } from './echo.controller.js' 4 | 5 | @Module({ 6 | controllers: [EchoController], 7 | }) 8 | export class EchoModule {} 9 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/src/echo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './echo.module.js' 2 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/src/grpc-http-proxy-app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { GrpcHttpProxyModule } from '@atls/nestjs-grpc-http-proxy' 4 | import { GrpcReflectionModule } from '@atls/nestjs-grpc-reflection' 5 | 6 | import { EchoModule } from './echo/index.js' 7 | import { serverOptions } from './server.options.js' 8 | 9 | @Module({ 10 | imports: [ 11 | GrpcReflectionModule.register(serverOptions.options), 12 | GrpcHttpProxyModule.register({ options: serverOptions.options }), 13 | EchoModule, 14 | ], 15 | }) 16 | export class GrpcHttpProxyAppModule {} 17 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/src/index.ts: -------------------------------------------------------------------------------- 1 | import './bootstrap.js' 2 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/src/proto.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.proto' 2 | -------------------------------------------------------------------------------- /examples/grpc-http-proxy/src/server.options.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import type { GrpcOptions } from '@nestjs/microservices' 4 | 5 | import { Transport } from '@nestjs/microservices' 6 | 7 | import reflection from '@atls/nestjs-grpc-reflection/proto/grpc/reflection/v1alpha/reflection.proto' 8 | 9 | import echo from '../proto/examples/echo/v1/echo.proto' 10 | 11 | export const serverOptions: GrpcOptions = { 12 | transport: Transport.GRPC, 13 | options: { 14 | package: ['grpc.reflection.v1', 'examples.echo.v1'], 15 | protoPath: [reflection, echo], 16 | url: '0.0.0.0:50051', 17 | loader: { 18 | arrays: true, 19 | keepCase: false, 20 | defaults: true, 21 | oneofs: true, 22 | }, 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /examples/grpc-playground/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1beta1 2 | 3 | plugins: 4 | - name: ts_proto 5 | out: proto 6 | opt: ts_proto_out=proto,nestJs=true,addGrpcMetadata=true,esModuleInterop=true,useOptionals=true 7 | -------------------------------------------------------------------------------- /examples/grpc-playground/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1beta1 2 | 3 | build: 4 | roots: 5 | - proto 6 | 7 | lint: 8 | use: 9 | - DEFAULT 10 | ignore: 11 | - grpc 12 | -------------------------------------------------------------------------------- /examples/grpc-playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/grpc-playground", 3 | "version": "0.0.1", 4 | "private": true, 5 | "license": "BSD 3-Clause", 6 | "type": "module", 7 | "scripts": { 8 | "dev": "yarn service dev", 9 | "proto:generate": "buf generate", 10 | "proto:lint": "buf lint" 11 | }, 12 | "dependencies": { 13 | "@atls/nestjs-grpc-playground": "workspace:*", 14 | "@atls/nestjs-grpc-reflection": "workspace:*", 15 | "@grpc/grpc-js": "1.11.2", 16 | "@grpc/proto-loader": "0.7.13", 17 | "@nestjs/common": "10.4.1", 18 | "@nestjs/core": "10.4.1", 19 | "@nestjs/microservices": "10.4.1", 20 | "@nestjs/testing": "10.4.1", 21 | "@types/long": "4.0.2", 22 | "google-protobuf": "3.21.4", 23 | "long": "4.0.0", 24 | "protobufjs": "7.4.0", 25 | "reflect-metadata": "0.2.2", 26 | "rxjs": "7.8.1" 27 | }, 28 | "externalDependencies": { 29 | "@nestjs/common/utils/load-package.util": "*" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/grpc-playground/proto/index.ts: -------------------------------------------------------------------------------- 1 | export * from './examples/playground/v1/playground.js' 2 | -------------------------------------------------------------------------------- /examples/grpc-playground/src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core' 2 | 3 | import { GrpcPlaygroundAppModule } from './grpc-playground-app.module.js' 4 | import { serverOptions } from './server.options.js' 5 | 6 | // eslint-disable-next-line @next/next/no-assign-module-variable 7 | declare const module: { 8 | hot?: { 9 | accept: () => void 10 | dispose: (callback: () => Promise) => void 11 | } 12 | } 13 | 14 | const bootstrap = async (): Promise => { 15 | const app = await NestFactory.create(GrpcPlaygroundAppModule) 16 | 17 | app.connectMicroservice(serverOptions) 18 | 19 | app.enableShutdownHooks() 20 | app.enableCors() 21 | 22 | await app.startAllMicroservices() 23 | await app.listen(3000) 24 | 25 | if (module.hot) { 26 | module.hot.accept() 27 | module.hot.dispose(async () => { 28 | await app.close() 29 | }) 30 | } 31 | } 32 | 33 | bootstrap() 34 | -------------------------------------------------------------------------------- /examples/grpc-playground/src/grpc-playground-app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { GrpcPlaygroundModule } from '@atls/nestjs-grpc-playground' 4 | 5 | import { PlaygroundModule } from './playground/index.js' 6 | import { serverOptions } from './server.options.js' 7 | 8 | @Module({ 9 | imports: [GrpcPlaygroundModule.register({ options: serverOptions.options }), PlaygroundModule], 10 | }) 11 | export class GrpcPlaygroundAppModule {} 12 | -------------------------------------------------------------------------------- /examples/grpc-playground/src/index.ts: -------------------------------------------------------------------------------- 1 | import './bootstrap.js' 2 | -------------------------------------------------------------------------------- /examples/grpc-playground/src/playground/index.ts: -------------------------------------------------------------------------------- 1 | export * from './playground.module.js' 2 | -------------------------------------------------------------------------------- /examples/grpc-playground/src/playground/playground.controller.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // @ts-nocheck 3 | import { Controller } from '@nestjs/common' 4 | import { GrpcMethod } from '@nestjs/microservices' 5 | 6 | @Controller() 7 | export class PlaygroundController { 8 | @GrpcMethod('PlaygroundService', 'Echo') 9 | echo(request) { 10 | return { 11 | pong: request.ping, 12 | } 13 | } 14 | 15 | @GrpcMethod('PlaygroundService', 'Switch') 16 | switch(request) { 17 | return request 18 | } 19 | 20 | @GrpcMethod('PlaygroundService', 'Text') 21 | text(request) { 22 | return request 23 | } 24 | 25 | @GrpcMethod('PlaygroundService', 'Number') 26 | number(request) { 27 | return request 28 | } 29 | 30 | @GrpcMethod('PlaygroundService', 'Enum') 31 | enum(request) { 32 | return request 33 | } 34 | 35 | @GrpcMethod('PlaygroundService', 'Nested') 36 | nested(request) { 37 | return request 38 | } 39 | 40 | @GrpcMethod('PlaygroundService', 'Repeated') 41 | repeated(request) { 42 | return request 43 | } 44 | 45 | @GrpcMethod('PlaygroundService', 'KitchenSink') 46 | kitchenSink(request) { 47 | return request 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /examples/grpc-playground/src/playground/playground.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { PlaygroundController } from './playground.controller.js' 4 | 5 | @Module({ 6 | controllers: [PlaygroundController], 7 | }) 8 | export class PlaygroundModule {} 9 | -------------------------------------------------------------------------------- /examples/grpc-playground/src/proto.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.proto' 2 | -------------------------------------------------------------------------------- /examples/grpc-playground/src/server.options.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import type { GrpcOptions } from '@nestjs/microservices' 4 | 5 | import { Transport } from '@nestjs/microservices' 6 | 7 | import reflection from '@atls/nestjs-grpc-reflection/proto/grpc/reflection/v1alpha/reflection.proto' 8 | 9 | import playground from '../proto/examples/playground/v1/playground.proto' 10 | 11 | export const serverOptions: GrpcOptions = { 12 | transport: Transport.GRPC, 13 | options: { 14 | package: ['grpc.reflection.v1', 'examples.playground.v1'], 15 | protoPath: [reflection, playground], 16 | url: '0.0.0.0:50051', 17 | loader: { 18 | arrays: true, 19 | keepCase: false, 20 | defaults: true, 21 | oneofs: true, 22 | }, 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /examples/grpc-reflection/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1beta1 2 | 3 | plugins: 4 | - name: ts_proto 5 | out: proto 6 | opt: ts_proto_out=proto,nestJs=true,addGrpcMetadata=true,esModuleInterop=true,useOptionals=true 7 | -------------------------------------------------------------------------------- /examples/grpc-reflection/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1beta1 2 | 3 | build: 4 | roots: 5 | - proto 6 | 7 | lint: 8 | use: 9 | - DEFAULT 10 | ignore: 11 | - grpc 12 | -------------------------------------------------------------------------------- /examples/grpc-reflection/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/grpc-reflection", 3 | "version": "0.0.0", 4 | "private": true, 5 | "license": "BSD 3-Clause", 6 | "type": "module", 7 | "scripts": { 8 | "dev": "yarn service dev", 9 | "proto:generate": "buf generate", 10 | "proto:lint": "buf lint" 11 | }, 12 | "dependencies": { 13 | "@atls/nestjs-grpc-reflection": "workspace:*", 14 | "@grpc/grpc-js": "1.11.2", 15 | "@grpc/proto-loader": "0.7.13", 16 | "@nestjs/common": "10.4.1", 17 | "@nestjs/core": "10.4.1", 18 | "@nestjs/microservices": "10.4.1", 19 | "@nestjs/testing": "10.4.1", 20 | "@types/long": "4.0.2", 21 | "google-protobuf": "3.21.4", 22 | "long": "4.0.0", 23 | "protobufjs": "7.4.0", 24 | "reflect-metadata": "0.2.2", 25 | "rxjs": "7.8.1" 26 | }, 27 | "externalDependencies": { 28 | "@nestjs/common/utils/load-package.util": "*" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/grpc-reflection/proto/examples/echo/v1/echo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package examples.echo.v1; 4 | 5 | service EchoService { 6 | rpc Echo (EchoRequest) returns (EchoResponse); 7 | } 8 | 9 | message EchoRequest { 10 | bool ping = 1; 11 | } 12 | 13 | message EchoResponse { 14 | bool pong = 1; 15 | } 16 | -------------------------------------------------------------------------------- /examples/grpc-reflection/proto/index.ts: -------------------------------------------------------------------------------- 1 | export * from './examples/echo/v1/echo.js' 2 | -------------------------------------------------------------------------------- /examples/grpc-reflection/src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core' 2 | 3 | import { GrpcReflectionAppModule } from './grpc-reflection-app.module.js' 4 | import { serverOptions } from './server.options.js' 5 | 6 | // eslint-disable-next-line @next/next/no-assign-module-variable 7 | declare const module: { 8 | hot?: { 9 | accept: () => void 10 | dispose: (callback: () => Promise) => void 11 | } 12 | } 13 | 14 | const bootstrap = async (): Promise => { 15 | const app = await NestFactory.create(GrpcReflectionAppModule) 16 | 17 | app.connectMicroservice(serverOptions) 18 | 19 | app.enableShutdownHooks() 20 | 21 | await app.startAllMicroservices() 22 | await app.listen(3000) 23 | 24 | if (module.hot) { 25 | module.hot.accept() 26 | module.hot.dispose(async () => { 27 | await app.close() 28 | }) 29 | } 30 | } 31 | 32 | bootstrap() 33 | -------------------------------------------------------------------------------- /examples/grpc-reflection/src/echo/echo.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller } from '@nestjs/common' 2 | import { GrpcMethod } from '@nestjs/microservices' 3 | 4 | import { EchoRequest } from '../../proto/index.js' 5 | import { EchoResponse } from '../../proto/index.js' 6 | 7 | @Controller() 8 | export class EchoController { 9 | @GrpcMethod('EchoService', 'Echo') 10 | echo(request: EchoRequest): EchoResponse { 11 | return { 12 | pong: request.ping, 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/grpc-reflection/src/echo/echo.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { EchoController } from './echo.controller.js' 4 | 5 | @Module({ 6 | controllers: [EchoController], 7 | }) 8 | export class EchoModule {} 9 | -------------------------------------------------------------------------------- /examples/grpc-reflection/src/echo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './echo.module.js' 2 | -------------------------------------------------------------------------------- /examples/grpc-reflection/src/grpc-reflection-app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { GrpcReflectionModule } from '@atls/nestjs-grpc-reflection' 4 | 5 | import { EchoModule } from './echo/index.js' 6 | import { serverOptions } from './server.options.js' 7 | 8 | @Module({ 9 | imports: [GrpcReflectionModule.register(serverOptions.options), EchoModule], 10 | }) 11 | export class GrpcReflectionAppModule {} 12 | -------------------------------------------------------------------------------- /examples/grpc-reflection/src/index.ts: -------------------------------------------------------------------------------- 1 | import './bootstrap.js' 2 | -------------------------------------------------------------------------------- /examples/grpc-reflection/src/proto.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.proto' 2 | -------------------------------------------------------------------------------- /examples/grpc-reflection/src/server.options.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import type { GrpcOptions } from '@nestjs/microservices' 4 | 5 | import { Transport } from '@nestjs/microservices' 6 | 7 | import reflection from '@atls/nestjs-grpc-reflection/proto/grpc/reflection/v1alpha/reflection.proto' 8 | 9 | import echo from '../proto/examples/echo/v1/echo.proto' 10 | 11 | export const serverOptions: GrpcOptions = { 12 | transport: Transport.GRPC, 13 | options: { 14 | package: ['grpc.reflection.v1', 'examples.echo.v1'], 15 | protoPath: [reflection, echo], 16 | url: '0.0.0.0:50051', 17 | loader: { 18 | arrays: true, 19 | keepCase: false, 20 | defaults: true, 21 | oneofs: true, 22 | }, 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nestjs", 3 | "private": true, 4 | "license": "BSD-3 Clause", 5 | "type": "module", 6 | "workspaces": [ 7 | "packages/**/*", 8 | "examples/**/*" 9 | ], 10 | "devDependencies": { 11 | "@atls/code-runtime": "2.1.7", 12 | "@types/node": "22.5.5", 13 | "typescript": "5.4.2" 14 | }, 15 | "packageManager": "yarn@4.7.0", 16 | "formatterIgnorePatterns": [ 17 | "**/*/CHANGELOG.md" 18 | ], 19 | "typecheckSkipLibCheck": true 20 | } 21 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/integration/test/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './wait-for-consume-count.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/integration/test/helpers/wait-for-consume-count.ts: -------------------------------------------------------------------------------- 1 | export const waitForConsumeCount = async ( 2 | expectedCount: number, 3 | consumeBatchs: Array, 4 | timeout = 5000 5 | ): Promise => { 6 | const endTime = Date.now() + timeout 7 | return new Promise((resolve, reject) => { 8 | const interval = setInterval(() => { 9 | if (consumeBatchs.length >= expectedCount) { 10 | clearInterval(interval) 11 | resolve() 12 | } else if (Date.now() > endTime) { 13 | clearInterval(interval) 14 | reject(new Error('Timeout waiting for messages to be processed')) 15 | } 16 | }, 100) 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/batch-queue/batch-queue.interface.ts: -------------------------------------------------------------------------------- 1 | export interface BatchQueueOptions { 2 | maxQueueLength: number 3 | maxTotalQueueLength: number 4 | maxQueues: number 5 | timeoutDuration: number 6 | } 7 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/batch-queue/batch-queue.types.ts: -------------------------------------------------------------------------------- 1 | export type QueueName = string 2 | export type ProcessorFn = (queueName: QueueName, item: Array) => Promise 3 | export type AddCond = { 4 | queueName: QueueName 5 | item: T 6 | } 7 | export type AddManyCond = { 8 | queueName: QueueName 9 | items: Array 10 | } 11 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/batch-queue/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './batch-queue.interface.js' 2 | export * from './batch-queue.js' 3 | export type * from './batch-queue.types.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/batch-queue/mutex.ts: -------------------------------------------------------------------------------- 1 | export class Mutex { 2 | private mutex = Promise.resolve() 3 | 4 | async lock(): Promise<() => void> { 5 | // eslint-disable-next-line @typescript-eslint/no-empty-function 6 | let begin: (unlock: () => void) => void = (unlock) => {} 7 | this.mutex = this.mutex.then(async () => new Promise(begin)) 8 | return new Promise((resolve) => { 9 | begin = resolve 10 | }) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/check-manager/check-manager.types.ts: -------------------------------------------------------------------------------- 1 | export type CheckName = string | symbol 2 | export type ChangeStateCallback = (state: boolean) => Promise | void 3 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/check-manager/index.ts: -------------------------------------------------------------------------------- 1 | export * from './check-manager.js' 2 | export type * from './check-manager.types.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/constants/batch-queue.constants.ts: -------------------------------------------------------------------------------- 1 | export const BATCH_QUEUE_CHECK_MANAGER = Symbol('BATCH_QUEUE_CHECK_MANAGER') 2 | export const BATCH_QUEUE = Symbol('BATCH_QUEUE') 3 | export const BATCH_QUEUE_MODULE_OPTIONS = Symbol('BATCH_QUEUE_MODULE_OPTIONS') 4 | export const BATCH_QUEUE_CONSUMER = Symbol('BATCH_QUEUE_CONSUMER') 5 | export const BATCH_QUEUE_PRODUCER = Symbol('BATCH_QUEUE_PRODUCER') 6 | export const BATCH_QUEUE_CHECKER = Symbol('BATCH_QUEUE_CHECKER') 7 | export const BATCH_QUEUE_STATE_HANDLER = Symbol('BATCH_QUEUE_STATE_HANDLER') 8 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/constants/index.ts: -------------------------------------------------------------------------------- 1 | export * from './batch-queue.constants.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/errors/batch-queue.errors.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-classes-per-file */ 2 | export class BaseQueueError extends Error {} 3 | 4 | export class CheckFailedError extends BaseQueueError {} 5 | 6 | export class MaxQueueCountError extends BaseQueueError {} 7 | 8 | export class MaxQueueLengthExceededError extends BaseQueueError {} 9 | 10 | export class MaxTotalLengthOfQueuesExceededError extends BaseQueueError {} 11 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/errors/index.ts: -------------------------------------------------------------------------------- 1 | export * from './batch-queue.errors.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './batch-queue/index.js' 2 | export * from './proxy-clases/index.js' 3 | export * from './module/index.js' 4 | export * from './errors/index.js' 5 | export * from './check-manager/index.js' 6 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/module/batch-queue-module-options.interface.ts: -------------------------------------------------------------------------------- 1 | import type { Type } from '@nestjs/common' 2 | import type { ModuleMetadata } from '@nestjs/common' 3 | 4 | import type { BatchQueueOptions } from '../batch-queue/index.js' 5 | import type { Consumer } from '../proxy-clases/index.js' 6 | 7 | export interface BatchQueueModuleOptions { 8 | core: BatchQueueOptions 9 | } 10 | 11 | export interface BatchQueueOptionsFactory { 12 | createBatchQueueOptions: () => BatchQueueModuleOptions | Promise 13 | } 14 | 15 | export interface BatchQueueConsumerFactory { 16 | createBatchQueueConsumer: () => Consumer | Promise 17 | } 18 | 19 | export interface BatchQueueModuleAsyncOptions extends Pick { 20 | useExisting?: Type 21 | useClass?: Type 22 | useFactory?: (...args: Array) => BatchQueueModuleOptions | Promise 23 | inject?: Array 24 | } 25 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/module/batch-queue.inject.ts: -------------------------------------------------------------------------------- 1 | import { Inject } from '@nestjs/common' 2 | 3 | import { BATCH_QUEUE_CONSUMER } from '../constants/index.js' 4 | import { BATCH_QUEUE_PRODUCER } from '../constants/index.js' 5 | import { BATCH_QUEUE_CHECKER } from '../constants/index.js' 6 | import { BATCH_QUEUE_STATE_HANDLER } from '../constants/index.js' 7 | 8 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type 9 | export const InjectBatchConsumer = () => Inject(BATCH_QUEUE_CONSUMER) 10 | 11 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type 12 | export const InjectBatchProducer = () => Inject(BATCH_QUEUE_PRODUCER) 13 | 14 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type 15 | export const InjectBatchChecker = () => Inject(BATCH_QUEUE_CHECKER) 16 | 17 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type 18 | export const InjectBatchStateHandler = () => Inject(BATCH_QUEUE_STATE_HANDLER) 19 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './batch-queue-module-options.interface.js' 2 | export * from '../constants/index.js' 3 | export * from './batch-queue.module.js' 4 | export * from './batch-queue.providers.js' 5 | export * from './batch-queue.inject.js' 6 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/proxy-clases/checker.ts: -------------------------------------------------------------------------------- 1 | import type { CheckManager } from '../check-manager/index.js' 2 | import type { CheckName } from '../check-manager/index.js' 3 | 4 | export class Checker { 5 | constructor(private checkManager: CheckManager) {} 6 | 7 | /** 8 | * Delegates to {@link CheckManager.createCheck} 9 | */ 10 | public createCheck(checkName: CheckName, initialState: boolean): void { 11 | this.checkManager.createCheck(checkName, initialState) 12 | } 13 | 14 | /** 15 | * Delegates to {@link CheckManager.changeState} 16 | */ 17 | public async changeState(checkName: CheckName, state: boolean): Promise { 18 | await this.checkManager.changeState(checkName, state) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/proxy-clases/consumer.ts: -------------------------------------------------------------------------------- 1 | import type { BatchQueue } from '../batch-queue/index.js' 2 | import type { ProcessorFn } from '../batch-queue/index.js' 3 | 4 | export class Consumer { 5 | constructor(private batchQueue: BatchQueue) {} 6 | 7 | /** 8 | * Delegates to {@link BatchQueue.processBatch} 9 | */ 10 | public consume(processor: ProcessorFn): void { 11 | this.batchQueue.processBatch(processor) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/proxy-clases/index.ts: -------------------------------------------------------------------------------- 1 | export * from './checker.js' 2 | export * from './consumer.js' 3 | export * from './producer.js' 4 | export * from './state-handler.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/proxy-clases/producer.ts: -------------------------------------------------------------------------------- 1 | import type { BatchQueue } from '../batch-queue/index.js' 2 | import type { QueueName } from '../batch-queue/index.js' 3 | 4 | export class Producer { 5 | constructor(private batchQueue: BatchQueue) {} 6 | 7 | /** 8 | * Delegates to {@link BatchQueue.add} 9 | */ 10 | async produce(queueName: QueueName, data: T): Promise { 11 | await this.batchQueue.add({ queueName, item: data }) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/nestjs-batch-queue/src/proxy-clases/state-handler.ts: -------------------------------------------------------------------------------- 1 | import type { CheckManager } from '../check-manager/index.js' 2 | import type { CheckName } from '../check-manager/index.js' 3 | import type { ChangeStateCallback } from '../check-manager/index.js' 4 | 5 | export class StateHandler { 6 | constructor(private checkManager: CheckManager) {} 7 | 8 | /** 9 | * Delegates to {@link CheckManager.handleChangeState} 10 | */ 11 | public handleChangeState(checkName: CheckName, callback: ChangeStateCallback): void { 12 | this.checkManager.handleChangeState(checkName, callback) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v2 2 | 3 | plugins: 4 | - local: protoc-gen-es 5 | opt: target=ts 6 | out: integration/gen 7 | - local: protoc-gen-connect-es 8 | opt: target=ts 9 | out: integration/gen 10 | - local: protoc-gen-interfaces 11 | opt: target=ts 12 | out: integration/gen/interfaces 13 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/integration/gen/interfaces/test_pb.ts: -------------------------------------------------------------------------------- 1 | // @generated by protoc-gen-interfaces 0.0.1 with parameter "target=ts" 2 | // @generated from file test.proto (package test, syntax proto3) 3 | /* eslint-disable */ 4 | // @ts-nocheck 5 | 6 | /** 7 | * @generated from message test.TestChild 8 | */ 9 | export interface TestChild { 10 | /** 11 | * @generated from field: string id = 1; 12 | */ 13 | id: string 14 | } 15 | 16 | /** 17 | * @generated from message test.ExecTestRequest 18 | */ 19 | export interface ExecTestRequest { 20 | /** 21 | * @generated from field: string id = 1; 22 | */ 23 | id: string 24 | 25 | /** 26 | * @generated from field: test.TestChild child = 2; 27 | */ 28 | child?: TestChild 29 | } 30 | 31 | /** 32 | * @generated from message test.ExecTestResponse 33 | */ 34 | export interface ExecTestResponse { 35 | /** 36 | * @generated from field: string id = 1; 37 | */ 38 | id: string 39 | } 40 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/integration/gen/test_connect.ts: -------------------------------------------------------------------------------- 1 | // @generated by protoc-gen-connect-es v1.6.1 with parameter "target=ts" 2 | // @generated from file test.proto (package test, syntax proto3) 3 | /* eslint-disable */ 4 | // @ts-nocheck 5 | 6 | import { MethodKind } from '@bufbuild/protobuf' 7 | 8 | import { ExecTestRequest } from './test_pb.js' 9 | import { ExecTestResponse } from './test_pb.js' 10 | 11 | /** 12 | * @generated from service test.TestService 13 | */ 14 | export const TestService = { 15 | typeName: 'test.TestService', 16 | methods: { 17 | /** 18 | * @generated from rpc test.TestService.TestValidation 19 | */ 20 | testValidation: { 21 | name: 'TestValidation', 22 | I: ExecTestRequest, 23 | O: ExecTestResponse, 24 | kind: MethodKind.Unary, 25 | }, 26 | }, 27 | } as const 28 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/integration/proto/test.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | service TestService { 6 | rpc TestValidation (ExecTestRequest) returns (ExecTestResponse) {} 7 | } 8 | 9 | message TestChild { 10 | string id = 1; 11 | } 12 | 13 | message ExecTestRequest { 14 | string id = 1; 15 | TestChild child = 2; 16 | } 17 | 18 | message ExecTestResponse { 19 | string id = 1; 20 | } 21 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/integration/src/connectrpc-errors-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { ValidationModule } from '@atls/nestjs-validation' 4 | 5 | import { TestController } from './test.controller.js' 6 | 7 | @Module({ 8 | controllers: [TestController], 9 | imports: [ValidationModule.register()], 10 | }) 11 | export class ConnectRpcErrorsIntegrationModule {} 12 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './connectrpc-errors-integration.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/integration/src/test.payload.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-classes-per-file */ 2 | 3 | import { Type } from 'class-transformer' 4 | import { ValidateNested } from 'class-validator' 5 | import { IsEmail } from 'class-validator' 6 | 7 | export class TestNestedPayload { 8 | @IsEmail() 9 | id!: string 10 | } 11 | 12 | export class TestPayload { 13 | @IsEmail() 14 | id!: string 15 | 16 | @ValidateNested() 17 | @Type(() => TestNestedPayload) 18 | child!: TestNestedPayload 19 | } 20 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/src/exception-factories/assertion.exception-factory.ts: -------------------------------------------------------------------------------- 1 | import type { AssertionError } from 'node:assert' 2 | 3 | import { Code } from '@connectrpc/connect' 4 | import { ConnectError } from '@connectrpc/connect' 5 | import { RpcException } from '@nestjs/microservices' 6 | 7 | export const assertionExceptionFactory = (error: AssertionError): RpcException => 8 | new RpcException(new ConnectError(error.message, Code.InvalidArgument)) 9 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/src/exception-factories/domain.exception-factory.ts: -------------------------------------------------------------------------------- 1 | import type { DomainError } from '@atls/core-errors' 2 | 3 | import { LogicalError } from '@atls/protobuf-rpc' 4 | import { Code } from '@connectrpc/connect' 5 | import { ConnectError } from '@connectrpc/connect' 6 | import { RpcException } from '@nestjs/microservices' 7 | 8 | export const domainExceptionFactory = (error: DomainError): RpcException => { 9 | const logicalError = new LogicalError({ 10 | id: error.name, 11 | message: error.message, 12 | }) 13 | 14 | return new RpcException( 15 | new ConnectError('Logical Error', Code.InvalidArgument, undefined, [logicalError]) 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/src/exception-factories/guard.exception-factory.ts: -------------------------------------------------------------------------------- 1 | import type { GuardErrors } from '@atls/guard-clause' 2 | 3 | import { ValidationError } from '@atls/protobuf-rpc' 4 | import { ValidationErrorMessage } from '@atls/protobuf-rpc' 5 | import { Code } from '@connectrpc/connect' 6 | import { ConnectError } from '@connectrpc/connect' 7 | import { RpcException } from '@nestjs/microservices' 8 | 9 | export const guardExceptionFactory = (errors: GuardErrors): RpcException => { 10 | const validationErrors: Array = errors.errors.map( 11 | (error) => 12 | new ValidationError({ 13 | id: error.code, 14 | property: error.parameter, 15 | messages: [ 16 | new ValidationErrorMessage({ 17 | id: error.code, 18 | constraint: error.message, 19 | }), 20 | ], 21 | }) 22 | ) 23 | 24 | return new RpcException( 25 | new ConnectError('Request validation failed', Code.InvalidArgument, undefined, validationErrors) 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/src/exception-factories/index.ts: -------------------------------------------------------------------------------- 1 | export * from './assertion.exception-factory.js' 2 | export * from './domain.exception-factory.js' 3 | export * from './guard.exception-factory.js' 4 | export * from './validation.exception-factory.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/src/exception-filters/index.ts: -------------------------------------------------------------------------------- 1 | export * from './connectrpc.exception-filter.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc-errors/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './exception-factories/index.js' 2 | export * from './exception-filters/index.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## [0.0.4](https://github.com/atls/nestjs/compare/@atls/nestjs-connectrpc@0.0.4...@atls/nestjs-connectrpc@0.0.4) (2025-04-03) 4 | 5 | 6 | 7 | 8 | 9 | 10 | ## [0.0.4](https://github.com/atls/nestjs/compare/@atls/nestjs-connectrpc@0.0.3...@atls/nestjs-connectrpc@0.0.4) (2025-01-24) 11 | 12 | 13 | 14 | 15 | 16 | 17 | ## [0.0.3](https://github.com/atls/nestjs/compare/@atls/nestjs-connectrpc@0.0.2...@atls/nestjs-connectrpc@0.0.3) (2025-01-24) 18 | 19 | 20 | ### Features 21 | 22 | 23 | * **nestjs:** update grpc reflection ([#341](https://github.com/atls/nestjs/issues/341)) ([3f78e26](https://github.com/atls/nestjs/commit/3f78e26340b9ba64eab425160e8cea7ba83a3538)) 24 | 25 | 26 | 27 | ## 0.0.2 (2025-01-22) 28 | 29 | ### Features 30 | 31 | - **common:** bump yarn, trigger release ([#338](https://github.com/atls/nestjs/issues/338)) ([9837d48](https://github.com/atls/nestjs/commit/9837d482f75928a3ac132d0306ab6de04d8a04b9)) 32 | - **connectrpc:** init ([#339](https://github.com/atls/nestjs/issues/339)) ([663389c](https://github.com/atls/nestjs/commit/663389cd20156a9c10e93d6dbb8326bf8dcac781)) 33 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc/README.md: -------------------------------------------------------------------------------- 1 | ConnectRpc migration @wolfcoded/nestjs-bufconnect 2 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc/src/connectrpc.constants.ts: -------------------------------------------------------------------------------- 1 | export const METHOD_DECORATOR_KEY = Symbol('METHOD_DECORATOR_KEY') 2 | 3 | export const STREAM_METHOD_DECORATOR_KEY = Symbol('STREAM_METHOD_DECORATOR_KEY') 4 | 5 | export const CONNECTRPC_TRANSPORT = Symbol('CONNECTRPC_TRANSPORT') 6 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc/src/custom-metadata.storage.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceType } from '@bufbuild/protobuf' 2 | 3 | export class CustomMetadataStore { 4 | private static instance: CustomMetadataStore 5 | 6 | private customMetadata: Map = new Map() 7 | 8 | // eslint-disable-next-line @typescript-eslint/no-empty-function 9 | private constructor() {} 10 | 11 | public static getInstance(): CustomMetadataStore { 12 | if (!CustomMetadataStore.instance) { 13 | CustomMetadataStore.instance = new CustomMetadataStore() 14 | } 15 | return CustomMetadataStore.instance 16 | } 17 | 18 | set(key: string, value: ServiceType): void { 19 | this.customMetadata.set(key, value) 20 | } 21 | 22 | get(key: string): ServiceType | undefined { 23 | return this.customMetadata.get(key) ?? undefined 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/nestjs-connectrpc/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './connectrpc.decorators.js' 2 | export * from './connectrpc.interfaces.js' 3 | export * from './connectrpc.strategy.js' 4 | export * from './connectrpc.server.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-cqrs-kafka-events/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## [0.0.1](https://github.com/atls/nestjs/compare/@atls/nestjs-cqrs-kafka-events@0.0.0...@atls/nestjs-cqrs-kafka-events@0.0.1) (2025-03-14) 4 | 5 | 6 | 7 | 8 | 9 | 10 | # 0.0.0 (2025-03-14) 11 | 12 | 13 | ### Bug Fixes 14 | 15 | 16 | * **nestjs-cqrs-kafka-events:** linter errors ([621dc8a](https://github.com/atls/nestjs/commit/621dc8a4c36e7961579073972303deb5cb232d40)) 17 | 18 | ### Features 19 | 20 | 21 | * **nestjs-cqrs-kafka-events:** init ([f35e71f](https://github.com/atls/nestjs/commit/f35e71f35b8afa4b8103752ae690f1280f1e88f9)) 22 | 23 | 24 | -------------------------------------------------------------------------------- /packages/nestjs-cqrs-kafka-events/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './messaging/index.js' 2 | export * from './module/index.js' 3 | 4 | export * from '@atls/nestjs-kafka' 5 | -------------------------------------------------------------------------------- /packages/nestjs-cqrs-kafka-events/src/messaging/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kafka.subscriber.js' 2 | export * from './kafka.publisher.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-cqrs-kafka-events/src/module/cqrs-kafka-events.module.constants.ts: -------------------------------------------------------------------------------- 1 | export const CQRS_KAFKA_EVENTS_MODULE_OPTIONS = Symbol('cqrs-kafka-events-module-options') 2 | -------------------------------------------------------------------------------- /packages/nestjs-cqrs-kafka-events/src/module/cqrs-kafka-events.module.interfaces.ts: -------------------------------------------------------------------------------- 1 | import type { KafkaConfig } from '@atls/nestjs-kafka' 2 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 3 | import type { Type } from '@nestjs/common/interfaces' 4 | 5 | export interface CqrsKafkaEventsModuleOptions extends Partial { 6 | groupId?: string 7 | } 8 | 9 | export interface CqrsKafkaEventsOptionsFactory { 10 | createCqrsKafkaEventsOptions: () => 11 | | CqrsKafkaEventsModuleOptions 12 | | Promise 13 | } 14 | 15 | export interface CqrsKafkaEventsModuleAsyncOptions extends Pick { 16 | useExisting?: Type 17 | useClass?: Type 18 | useFactory?: ( 19 | ...args: Array 20 | ) => CqrsKafkaEventsModuleOptions | Promise 21 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 22 | inject?: Array 23 | } 24 | -------------------------------------------------------------------------------- /packages/nestjs-cqrs-kafka-events/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export * from './cqrs-kafka-events.module.constants.js' 2 | export * from './cqrs-kafka-events.module.js' 3 | export type * from './cqrs-kafka-events.module.interfaces.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-cqrs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## [0.0.3](https://github.com/atls/nestjs/compare/@atls/nestjs-cqrs@0.0.2...@atls/nestjs-cqrs@0.0.3) (2025-03-14) 4 | 5 | 6 | 7 | 8 | 9 | 10 | ## 0.0.2 (2025-03-14) 11 | 12 | 13 | ### Bug Fixes 14 | 15 | 16 | * **nestjs-cqrs:** typecheck on release ([349126c](https://github.com/atls/nestjs/commit/349126c0ae7eeee333e81e242dbe4f476eae4521)) 17 | 18 | ### Features 19 | 20 | 21 | * **nestjs-cqrs:** init package ([d4d1849](https://github.com/atls/nestjs/commit/d4d1849fcb9d7ef36fc3c13ec072e0985c3b239b)) 22 | 23 | 24 | -------------------------------------------------------------------------------- /packages/nestjs-cqrs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@atls/nestjs-cqrs", 3 | "version": "0.0.3", 4 | "license": "BSD-3-Clause", 5 | "type": "module", 6 | "exports": { 7 | "./package.json": "./package.json", 8 | ".": "./src/index.ts" 9 | }, 10 | "main": "src/index.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "build": "yarn library build", 16 | "prepack": "yarn run build", 17 | "postpack": "rm -rf dist" 18 | }, 19 | "devDependencies": { 20 | "@nestjs/common": "^10.0.5", 21 | "@nestjs/core": "^10.0.5", 22 | "@nestjs/cqrs": "^10.2.5", 23 | "reflect-metadata": "^0.1.13", 24 | "rxjs": "^7.8.1" 25 | }, 26 | "peerDependencies": { 27 | "@nestjs/common": "^10", 28 | "@nestjs/core": "^10", 29 | "@nestjs/cqrs": "^10", 30 | "reflect-metadata": "^0.1", 31 | "rxjs": "^7" 32 | }, 33 | "publishConfig": { 34 | "exports": { 35 | "./package.json": "./package.json", 36 | ".": { 37 | "import": "./dist/index.js", 38 | "types": "./dist/index.d.ts", 39 | "default": "./dist/index.js" 40 | } 41 | }, 42 | "main": "dist/index.js", 43 | "typings": "dist/index.d.ts" 44 | }, 45 | "typecheckSkipLibCheck": true 46 | } 47 | -------------------------------------------------------------------------------- /packages/nestjs-cqrs/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './cqrs.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-dataloader/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const GET_LOADER_CONTEXT_KEY: string = 'GET_LOADER_CONTEXT_KEY' 2 | -------------------------------------------------------------------------------- /packages/nestjs-dataloader/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './order-result-by-key.decorator.js' 2 | export * from './loader.decorator.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-dataloader/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './decorators/index.js' 2 | export * from './interceptors/index.js' 3 | export type * from './interfaces/index.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-dataloader/src/interceptors/index.ts: -------------------------------------------------------------------------------- 1 | export * from './data-loader.interceptor.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-dataloader/src/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './nest-dataloader.interfaces.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-dataloader/src/interfaces/nest-dataloader.interfaces.ts: -------------------------------------------------------------------------------- 1 | import type DataLoader from 'dataloader' 2 | 3 | export interface NestDataLoader { 4 | generateDataLoader: () => DataLoader 5 | } 6 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/integration/src/exec.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller } from '@nestjs/common' 2 | import { Get } from '@nestjs/common' 3 | import { Render } from '@nestjs/common' 4 | import { Res } from '@nestjs/common' 5 | 6 | @Controller('exec') 7 | export class ExecController { 8 | @Get('/simple') 9 | @Render('/render/simple') 10 | simple(): Record { 11 | return {} 12 | } 13 | 14 | @Get('/params') 15 | @Render('/render/params') 16 | params(): Record { 17 | return { 18 | param: 'value', 19 | } 20 | } 21 | 22 | @Get('/res-render-params') 23 | // @ts-expect-error unsafe method 24 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types 25 | resRenderParams(@Res() res): void { 26 | // eslint-disable-next-line @typescript-eslint/no-unsafe-call 27 | res.render('/render/params', { 28 | param: 'value', 29 | }) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/integration/src/external-renderer-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { ExternalRendererModule } from '../../src/index.js' 4 | import { ExecController } from './exec.controller.js' 5 | import { RenderController } from './render.controller.js' 6 | 7 | @Module({ 8 | imports: [ 9 | ExternalRendererModule.register({ 10 | url: 'http://localhost:3000', 11 | }), 12 | ], 13 | controllers: [RenderController, ExecController], 14 | }) 15 | export class ExternalRendererIntegrationModule {} 16 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './external-renderer-integration.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/integration/src/render.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller } from '@nestjs/common' 2 | import { Body } from '@nestjs/common' 3 | import { Post } from '@nestjs/common' 4 | 5 | @Controller('render') 6 | export class RenderController { 7 | @Post('simple') 8 | simple(): string { 9 | return 'content' 10 | } 11 | 12 | @Post('params') 13 | // @ts-expect-error unsafe method 14 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type 15 | params(@Body() body) { 16 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return 17 | return body.param 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/src/config/external-renderer-env.config.ts: -------------------------------------------------------------------------------- 1 | import type { ExternalRendererOptionsFactory } from '../module/index.js' 2 | import type { ExternalRendererModuleOptions } from '../module/index.js' 3 | 4 | export class ExternalRendererEnvConfig implements ExternalRendererOptionsFactory { 5 | createExternalRendererOptions(): ExternalRendererModuleOptions { 6 | if (!process.env.EXTERNAL_RENDERER_URL) { 7 | throw new Error('EXTERNAL_RENDERER_URL configuration variable required') 8 | } 9 | 10 | return { 11 | url: process.env.EXTERNAL_RENDERER_URL, 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export * from './external-renderer-env.config.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module/index.js' 2 | export * from './renderer/index.js' 3 | export * from './config/index.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/src/module/external-renderer-module-options.interface.ts: -------------------------------------------------------------------------------- 1 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 2 | import type { Type } from '@nestjs/common/interfaces' 3 | 4 | export interface ExternalRendererModuleOptions { 5 | url: string 6 | } 7 | 8 | export interface ExternalRendererOptionsFactory { 9 | createExternalRendererOptions: () => 10 | | ExternalRendererModuleOptions 11 | | Promise 12 | } 13 | 14 | export interface ExternalRendererModuleAsyncOptions extends Pick { 15 | useExisting?: Type 16 | useClass?: Type 17 | useFactory?: ( 18 | ...args: Array 19 | ) => ExternalRendererModuleOptions | Promise 20 | inject?: Array 21 | } 22 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/src/module/external-renderer.constants.ts: -------------------------------------------------------------------------------- 1 | export const EXTERNAL_RENDERER_MODULE_OPTIONS = 'EXTERNAL_RENDERER_MODULE_OPTIONS' 2 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/src/module/external-renderer.providers.ts: -------------------------------------------------------------------------------- 1 | import type { Provider } from '@nestjs/common' 2 | 3 | import type { ExternalRendererModuleOptions } from './external-renderer-module-options.interface.js' 4 | 5 | import { ExternalRenderer } from '../renderer/index.js' 6 | import { EXTERNAL_RENDERER_MODULE_OPTIONS } from './external-renderer.constants.js' 7 | 8 | export const createExternalRendererOptionsProvider = ( 9 | options: ExternalRendererModuleOptions 10 | ): Array => [ 11 | { 12 | provide: EXTERNAL_RENDERER_MODULE_OPTIONS, 13 | useValue: options, 14 | }, 15 | ] 16 | 17 | export const createExternalRendererProvider = (): Array => [ExternalRenderer] 18 | 19 | export const createExternalRendererExportsProvider = (): Array => [] 20 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './external-renderer-module-options.interface.js' 2 | export * from './external-renderer.constants.js' 3 | export * from './external-renderer.module.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-external-renderer/src/renderer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './express-external-renderer.view.js' 2 | export * from './external.renderer.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## [0.0.17](https://github.com/atls/nestjs/compare/@atls/nestjs-gateway@0.0.16...@atls/nestjs-gateway@0.0.17) (2025-01-24) 4 | 5 | 6 | ### Features 7 | 8 | 9 | * **nestjs:** update grpc reflection ([#341](https://github.com/atls/nestjs/issues/341)) ([3f78e26](https://github.com/atls/nestjs/commit/3f78e26340b9ba64eab425160e8cea7ba83a3538)) 10 | 11 | 12 | 13 | ## 0.0.16 (2025-01-22) 14 | 15 | ### Features 16 | 17 | - **batch-queue:** init ([6ecbffa](https://github.com/atls/nestjs/commit/6ecbffa3fc54f9bb33ac1ae57b274772b99c8e9d)) 18 | - **common:** bump yarn, trigger release ([#338](https://github.com/atls/nestjs/issues/338)) ([9837d48](https://github.com/atls/nestjs/commit/9837d482f75928a3ac132d0306ab6de04d8a04b9)) 19 | - **connectrpc:** init ([#339](https://github.com/atls/nestjs/issues/339)) ([663389c](https://github.com/atls/nestjs/commit/663389cd20156a9c10e93d6dbb8326bf8dcac781)) 20 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/integration/src/gateway-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { GatewayModule } from '../../src/index.js' 4 | import { MoviesController } from './movies.controller.js' 5 | 6 | @Module({ 7 | imports: [GatewayModule.register()], 8 | controllers: [MoviesController], 9 | }) 10 | export class GatewayIntegrationModule {} 11 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './gateway-integration.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/integration/src/service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package tech.atls; 4 | 5 | service ExampleService { 6 | rpc getMovies (MovieRequest) returns (MoviesResult) {} 7 | rpc GetMetadata (GetMetadataRequest) returns (GetMetadataResponse) {} 8 | rpc GetError (GetErrorRequest) returns (GetErrorResponse) {} 9 | rpc GetMustRename (GetMustRenameRequest) returns (GetMustRenameResponse) {} 10 | rpc SendMovies (MovieRequest) returns (MoviesResult) {} 11 | } 12 | 13 | message Movie { 14 | string name = 1; 15 | int32 year = 2; 16 | float rating = 3; 17 | } 18 | 19 | message MovieRequest { 20 | } 21 | 22 | message MoviesResult { 23 | repeated Movie result = 1; 24 | } 25 | 26 | message GetMetadataRequest { 27 | 28 | } 29 | 30 | message GetMetadataResponse { 31 | string authorization = 1; 32 | } 33 | 34 | message GetErrorRequest { 35 | 36 | } 37 | 38 | message GetErrorResponse { 39 | string result = 1; 40 | } 41 | 42 | message GetMustRenameRequest { 43 | 44 | } 45 | 46 | message GetMustRenameResponse { 47 | string result = 1; 48 | } -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/enums/gateway-source-type.enum.ts: -------------------------------------------------------------------------------- 1 | export enum GatewaySourceType { 2 | GRPC = 'grpc', 3 | } 4 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/enums/index.ts: -------------------------------------------------------------------------------- 1 | export * from './gateway-source-type.enum.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/index.ts: -------------------------------------------------------------------------------- 1 | export { PubSub } from 'graphql-subscriptions' 2 | 3 | export * from './enums/index.js' 4 | export * from './module/index.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/mesh/format.error.ts: -------------------------------------------------------------------------------- 1 | import type { ServiceError } from '@grpc/grpc-js' 2 | 3 | import { ErrorStatus } from '@atls/grpc-error-status' 4 | 5 | const isGrpcErrorStatus = (error: { code: number; metadata: any; details: any }): boolean => 6 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return 7 | error.code >= 0 && error.metadata && error.details 8 | 9 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type 10 | export const formatError = (error: { extensions: { exception: ServiceError } }) => { 11 | if (error.extensions?.exception && isGrpcErrorStatus(error.extensions.exception)) { 12 | // @ts-expect-error 13 | // eslint-disable-next-line no-param-reassign 14 | error.extensions.exception = ErrorStatus.fromServiceError(error.extensions.exception).toObject() 15 | } 16 | 17 | return error 18 | } 19 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/mesh/graphql-mesh.logger.ts: -------------------------------------------------------------------------------- 1 | import type { Logger as MeshLogger } from '@graphql-mesh/types' 2 | 3 | import { Logger } from '@atls/logger' 4 | 5 | export class GraphQLMeshLogger implements MeshLogger { 6 | private logger: Logger 7 | 8 | constructor(public name: string) { 9 | this.logger = new Logger(name) 10 | } 11 | 12 | log(message: string): void { 13 | this.logger.info(message) 14 | } 15 | 16 | warn(message: string): void { 17 | this.logger.warn(message) 18 | } 19 | 20 | info(message: string): void { 21 | this.logger.info(message) 22 | } 23 | 24 | error(message: string): void { 25 | this.logger.error(message) 26 | } 27 | 28 | debug(message: string): void { 29 | this.logger.debug(message) 30 | } 31 | 32 | child(name: string): MeshLogger { 33 | const logger = new GraphQLMeshLogger(name) 34 | 35 | logger.logger = this.logger.child(name) 36 | 37 | return logger 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/mesh/graphql-mesh.schema-dumper.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/naming-convention */ 2 | /* eslint-disable no-underscore-dangle */ 3 | 4 | import type { OnModuleInit } from '@nestjs/common' 5 | 6 | import { Injectable } from '@nestjs/common' 7 | import { printSchemaWithDirectives } from '@graphql-tools/utils' 8 | import { promises as fs } from 'fs' 9 | import { join } from 'path' 10 | 11 | import { GraphQLMesh } from './graphql.mesh.js' 12 | 13 | declare const __non_webpack_require__: any 14 | 15 | @Injectable() 16 | export class GraphQLMeshSchemaDumper implements OnModuleInit { 17 | constructor(private readonly mesh: GraphQLMesh) {} 18 | 19 | async onModuleInit(): Promise { 20 | if (process.env.NODE_ENV === 'development') { 21 | const { schema } = await this.mesh.getInstance() 22 | 23 | await fs.writeFile( 24 | join( 25 | typeof __non_webpack_require__ === 'undefined' ? process.cwd() : `${__dirname}/../`, 26 | 'gateway.graphql' 27 | ), 28 | // eslint-disable-next-line @typescript-eslint/no-unsafe-argument 29 | printSchemaWithDirectives(schema) 30 | ) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/mesh/graphql.mesh.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error 2 | import type { MeshInstance } from '@graphql-mesh/runtime' 3 | 4 | import { Injectable } from '@nestjs/common' 5 | // @ts-expect-error 6 | import { getMesh } from '@graphql-mesh/runtime' 7 | 8 | import { GraphQLMeshConfig } from './graphql-mesh.config.js' 9 | 10 | @Injectable() 11 | export class GraphQLMesh { 12 | private mesh!: MeshInstance 13 | 14 | constructor(private readonly config: GraphQLMeshConfig) {} 15 | 16 | async getInstance(): Promise { 17 | if (!this.mesh) { 18 | // eslint-disable-next-line @typescript-eslint/no-unsafe-call 19 | this.mesh = await getMesh(await this.config.create()) 20 | } 21 | 22 | return this.mesh 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/mesh/handlers/grpc/patch-long-js.ts: -------------------------------------------------------------------------------- 1 | import Long from 'long' 2 | 3 | function patchLongJs(): void { 4 | const originalLongFromValue = Long.fromValue.bind(Long) 5 | Long.fromValue = (value: Long | number | string): Long => { 6 | if (typeof value === 'bigint') { 7 | return Long.fromValue((value as bigint).toString()) 8 | } 9 | return originalLongFromValue(value) 10 | } 11 | } 12 | patchLongJs() 13 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/mesh/handlers/grpc/scalars.ts: -------------------------------------------------------------------------------- 1 | type ScalarMap = Map 2 | 3 | const SCALARS: ScalarMap = new Map([ 4 | ['bool', 'Boolean'], 5 | ['bytes', 'Byte'], 6 | ['double', 'Float'], 7 | ['fixed32', 'Int'], 8 | ['fixed64', 'BigInt'], 9 | ['float', 'Float'], 10 | ['int32', 'Int'], 11 | ['int64', 'BigInt'], 12 | ['sfixed32', 'Int'], 13 | ['sfixed64', 'BigInt'], 14 | ['sint32', 'Int'], 15 | ['sint64', 'BigInt'], 16 | ['string', 'String'], 17 | ['uint32', 'UnsignedInt'], 18 | ['uint64', 'BigInt'], // A new scalar might be needed 19 | ]) 20 | 21 | export function isScalarType(type: string): boolean { 22 | return SCALARS.has(type) 23 | } 24 | 25 | export function getGraphQLScalar(scalarType: string): string { 26 | const gqlScalar = SCALARS.get(scalarType) 27 | if (!gqlScalar) { 28 | throw new Error(`Could not find GraphQL Scalar for type ${scalarType}`) 29 | } 30 | // @ts-expect-error 31 | return SCALARS.get(scalarType) 32 | } 33 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/mesh/index.ts: -------------------------------------------------------------------------------- 1 | export * from './graphql-mesh.handler.js' 2 | export * from './graphql-mesh.config.js' 3 | export * from './graphql.mesh.js' 4 | 5 | export * from './graphql-mesh.schema-dumper.js' 6 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/module/gateway.constants.ts: -------------------------------------------------------------------------------- 1 | export const GATEWAY_MODULE_OPTIONS = `GATEWAY_MODULE_OPTIONS` 2 | -------------------------------------------------------------------------------- /packages/nestjs-gateway/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './gateway-module-options.interface.js' 2 | export * from './gateway.constants.js' 3 | export * from './gateway.module.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-gcs-client/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 0.0.1 (2025-03-15) 4 | 5 | 6 | ### Features 7 | 8 | 9 | * **nestjs-gcs-client:** init ([167725e](https://github.com/atls/nestjs/commit/167725ec09109e7015db1af5c3e9011eca67716f)) 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/nestjs-gcs-client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@atls/nestjs-gcs-client", 3 | "version": "0.0.1", 4 | "license": "BSD-3-Clause", 5 | "type": "module", 6 | "exports": { 7 | "./package.json": "./package.json", 8 | ".": "./src/index.ts" 9 | }, 10 | "main": "src/index.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "build": "yarn library build", 16 | "prepack": "yarn run build", 17 | "postpack": "rm -rf dist" 18 | }, 19 | "dependencies": { 20 | "@google-cloud/storage": "7.0.1" 21 | }, 22 | "devDependencies": { 23 | "@nestjs/common": "10.4.15", 24 | "@nestjs/core": "10.4.15", 25 | "reflect-metadata": "0.2.2", 26 | "rxjs": "7.8.1" 27 | }, 28 | "peerDependencies": { 29 | "@nestjs/common": "^10", 30 | "@nestjs/core": "^10", 31 | "reflect-metadata": "^0.2", 32 | "rxjs": "^7" 33 | }, 34 | "publishConfig": { 35 | "exports": { 36 | "./package.json": "./package.json", 37 | ".": { 38 | "import": "./dist/index.js", 39 | "types": "./dist/index.d.ts", 40 | "default": "./dist/index.js" 41 | } 42 | }, 43 | "main": "dist/index.js", 44 | "typings": "dist/index.d.ts" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/nestjs-gcs-client/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@google-cloud/storage' 2 | 3 | export * from './module/index.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-gcs-client/src/module/gcs-client.config-factory.ts: -------------------------------------------------------------------------------- 1 | import type { StorageOptions } from '@google-cloud/storage' 2 | 3 | // eslint-disable-next-line @typescript-eslint/consistent-type-imports 4 | import type { GcsClientModuleOptions } from './gcs-client.module.interfaces.js' 5 | 6 | import { Injectable } from '@nestjs/common' 7 | import { Inject } from '@nestjs/common' 8 | 9 | import { GCS_CLIENT_MODULE_OPTIONS } from './gcs-client.module.constants.js' 10 | 11 | @Injectable() 12 | export class GcsClientConfigFactory { 13 | constructor( 14 | @Inject(GCS_CLIENT_MODULE_OPTIONS) 15 | private readonly options: GcsClientModuleOptions 16 | ) {} 17 | 18 | createGcsClientOptions(options: GcsClientModuleOptions = {}): StorageOptions { 19 | return { 20 | apiEndpoint: options.apiEndpoint || this.options.apiEndpoint || process.env.GCS_API_ENDPOINT, 21 | keyFilename: options.keyFilename || this.options.keyFilename || process.env.GCS_KEY_FILENAME, 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/nestjs-gcs-client/src/module/gcs-client.factory.ts: -------------------------------------------------------------------------------- 1 | import type { GcsClientModuleOptions } from './gcs-client.module.interfaces.js' 2 | 3 | import { Storage } from '@google-cloud/storage' 4 | import { Injectable } from '@nestjs/common' 5 | 6 | import { GcsClientConfigFactory } from './gcs-client.config-factory.js' 7 | 8 | @Injectable() 9 | export class GcsClientFactory { 10 | constructor(private readonly configFactory: GcsClientConfigFactory) {} 11 | 12 | create(options: GcsClientModuleOptions = {}): Storage { 13 | return new Storage(this.configFactory.createGcsClientOptions(options)) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/nestjs-gcs-client/src/module/gcs-client.module.constants.ts: -------------------------------------------------------------------------------- 1 | export const GCS_CLIENT_MODULE_OPTIONS = Symbol('gcs-client-module-options') 2 | -------------------------------------------------------------------------------- /packages/nestjs-gcs-client/src/module/gcs-client.module.interfaces.ts: -------------------------------------------------------------------------------- 1 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 2 | import type { Type } from '@nestjs/common/interfaces' 3 | 4 | export interface GcsClientModuleOptions { 5 | apiEndpoint?: string 6 | keyFilename?: string 7 | } 8 | 9 | export interface GcsClientOptionsFactory { 10 | createGcsClientOptions: () => GcsClientModuleOptions | Promise 11 | } 12 | 13 | export interface GcsClientModuleAsyncOptions extends Pick { 14 | useExisting?: Type 15 | useClass?: Type 16 | useFactory?: (...args: Array) => GcsClientModuleOptions | Promise 17 | inject?: Array 18 | } 19 | -------------------------------------------------------------------------------- /packages/nestjs-gcs-client/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export * from './gcs-client.module.interfaces.js' 2 | export * from './gcs-client.module.constants.js' 3 | export * from './gcs-client.config-factory.js' 4 | export * from './gcs-client.factory.js' 5 | export * from './gcs-client.module.js' 6 | -------------------------------------------------------------------------------- /packages/nestjs-graphql-redis-subscriptions/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from 'graphql-subscriptions' 2 | export * from './module/index.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-graphql-redis-subscriptions/src/module/graphql-redis-subscriptions.module.interfaces.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-empty-interface */ 2 | 3 | import type { PubSubRedisOptions } from 'graphql-redis-subscriptions/dist/redis-pubsub.js' 4 | 5 | export interface GraphQLRedisSubscriptionsModuleOptions 6 | extends Omit {} 7 | -------------------------------------------------------------------------------- /packages/nestjs-graphql-redis-subscriptions/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './graphql-redis-subscriptions.module.interfaces.js' 2 | export * from './graphql-redis-subscriptions.module.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 0.1.1 (2025-02-12) 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/integration/src/grpc-errors-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { TestController } from './test.controller.js' 4 | 5 | @Module({ 6 | controllers: [TestController], 7 | }) 8 | export class GrpcErrorsIntegrationModule {} 9 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-errors-integration.module.js' 2 | export * from './proto.options.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/integration/src/proto.options.ts: -------------------------------------------------------------------------------- 1 | import type { GrpcOptions } from '@nestjs/microservices' 2 | 3 | import { Transport } from '@nestjs/microservices' 4 | import path from 'path' 5 | 6 | export const serverOptions: GrpcOptions = { 7 | transport: Transport.GRPC, 8 | options: { 9 | package: ['test'], 10 | protoPath: [path.join(__dirname, './test.proto')], 11 | url: '0.0.0.0:50051', 12 | loader: { 13 | arrays: true, 14 | keepCase: true, 15 | defaults: true, 16 | oneofs: true, 17 | includeDirs: [], 18 | }, 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/integration/src/test.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller } from '@nestjs/common' 2 | import { UsePipes } from '@nestjs/common' 3 | import { GrpcMethod } from '@nestjs/microservices' 4 | 5 | import { GrpcValidationPipe } from '../../src/index.js' 6 | import { TestDto } from './test.dto.js' 7 | 8 | @Controller() 9 | export class TestController { 10 | @GrpcMethod('TestService', 'TestValidation') 11 | @UsePipes(new GrpcValidationPipe()) 12 | test({ id }: TestDto): { id: string } { 13 | return { 14 | id, 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/integration/src/test.dto.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-classes-per-file */ 2 | 3 | import { Type } from 'class-transformer' 4 | import { ValidateNested } from 'class-validator' 5 | import { IsEmail } from 'class-validator' 6 | 7 | export class TestNestedDto { 8 | @IsEmail() 9 | id!: string 10 | } 11 | 12 | export class TestDto { 13 | @IsEmail() 14 | id!: string 15 | 16 | @ValidateNested() 17 | @Type(() => TestNestedDto) 18 | child!: TestNestedDto 19 | } 20 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/integration/src/test.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | service TestService { 6 | rpc TestValidation (ExecTestRequest) returns (ExecTestResponse) {} 7 | } 8 | 9 | message TestChild { 10 | string id = 1; 11 | } 12 | 13 | message ExecTestRequest { 14 | string id = 1; 15 | TestChild child = 2; 16 | } 17 | 18 | message ExecTestResponse { 19 | string id = 1; 20 | } 21 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/src/exception-factories/assertion.exception-factory.ts: -------------------------------------------------------------------------------- 1 | import type { AssertionError } from 'node:assert/strict' 2 | 3 | import * as grpcErrorStatus from '@atls/grpc-error-status' 4 | import { RpcException } from '@nestjs/microservices' 5 | import { status } from '@grpc/grpc-js' 6 | 7 | const { ErrorStatus } = grpcErrorStatus 8 | 9 | export const assertionExceptionFactory = (error: AssertionError): RpcException => { 10 | const errorStatus = new ErrorStatus(status.INVALID_ARGUMENT, error.message) 11 | 12 | return new RpcException(errorStatus.toServiceError()) 13 | } 14 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/src/exception-factories/index.ts: -------------------------------------------------------------------------------- 1 | export * from './assertion.exception-factory.js' 2 | export * from './grpc-validation.exception-factory.js' 3 | export * from './internal-server.exception-factory.js' 4 | export * from './not-found.exception-factory.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/src/exception-factories/internal-server.exception-factory.ts: -------------------------------------------------------------------------------- 1 | import type { InternalServerErrorException } from '@nestjs/common' 2 | 3 | import * as grpcErrorStatus from '@atls/grpc-error-status' 4 | import { RpcException } from '@nestjs/microservices' 5 | import { status } from '@grpc/grpc-js' 6 | 7 | const { ErrorStatus } = grpcErrorStatus 8 | 9 | export const internalServerExceptionFactory = ( 10 | error: InternalServerErrorException 11 | ): RpcException => { 12 | const errorStatus = new ErrorStatus(status.INTERNAL, error.message) 13 | 14 | return new RpcException(errorStatus.toServiceError()) 15 | } 16 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/src/exception-factories/not-found.exception-factory.ts: -------------------------------------------------------------------------------- 1 | import type { NotFoundException } from '@nestjs/common' 2 | 3 | import * as grpcErrorStatus from '@atls/grpc-error-status' 4 | import { RpcException } from '@nestjs/microservices' 5 | import { status } from '@grpc/grpc-js' 6 | 7 | const { ErrorStatus } = grpcErrorStatus 8 | 9 | export const notFoundExceptionFactory = (error: NotFoundException): RpcException => { 10 | const errorStatus = new ErrorStatus(status.NOT_FOUND, error.message) 11 | 12 | return new RpcException(errorStatus.toServiceError()) 13 | } 14 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/src/exception-filters/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc.exception-filter.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './exception-filters/index.js' 2 | export * from './exception-factories/index.js' 3 | export * from './pipes/index.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/src/pipes/grpc-validation.pipe.ts: -------------------------------------------------------------------------------- 1 | import type { ValidationPipeOptions } from '@nestjs/common' 2 | 3 | import { ValidationPipe } from '@nestjs/common' 4 | 5 | import { grpcValidationExceptionFactory } from '../exception-factories/index.js' 6 | 7 | export class GrpcValidationPipe extends ValidationPipe { 8 | constructor(options?: ValidationPipeOptions) { 9 | super({ 10 | ...(options || {}), 11 | transform: typeof options?.transform === `undefined` ? true : options?.transform, 12 | exceptionFactory: grpcValidationExceptionFactory || options?.exceptionFactory, 13 | }) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-errors/src/pipes/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-validation.pipe.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/integration/src/grpc-http-proxy-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { GrpcHttpProxyModule } from '../../src/index.js' 4 | import { NopeAuthenticator } from './nope.authenticator.js' 5 | import { TestController } from './test.controller.js' 6 | import { serverOptions } from './proto.options.js' 7 | 8 | @Module({ 9 | imports: [ 10 | GrpcHttpProxyModule.register({ 11 | options: serverOptions.options, 12 | authenticator: new NopeAuthenticator(), 13 | }), 14 | ], 15 | controllers: [TestController], 16 | }) 17 | export class GrpcHttpProxyIntegrationModule {} 18 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-http-proxy-integration.module.js' 2 | export * from './nope.authenticator.js' 3 | export * from './proto.options.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/integration/src/nope.authenticator.ts: -------------------------------------------------------------------------------- 1 | import type { Authenticator } from '../../src/index.js' 2 | 3 | export class NopeAuthenticator implements Authenticator { 4 | async execute(): Promise { 5 | return Promise.resolve('nope') 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/integration/src/proto.options.ts: -------------------------------------------------------------------------------- 1 | import type { GrpcOptions } from '@nestjs/microservices' 2 | 3 | import { Transport } from '@nestjs/microservices' 4 | import path from 'path' 5 | 6 | export const serverOptions: GrpcOptions = { 7 | transport: Transport.GRPC, 8 | options: { 9 | package: ['test'], 10 | protoPath: [path.join(__dirname, './test.proto')], 11 | url: '0.0.0.0:50051', 12 | loader: { 13 | arrays: true, 14 | keepCase: true, 15 | defaults: true, 16 | oneofs: true, 17 | includeDirs: [], 18 | }, 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/integration/src/test.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | service TestService { 6 | rpc Test (ExecTestRequest) returns (ExecTestResponse) {} 7 | rpc TestError (ExecTestRequest) returns (ExecTestResponse) {} 8 | rpc TestStream (stream ExecTestRequest) returns (stream ExecTestResponse) {} 9 | rpc TestAuth (ExecTestRequest) returns (ExecTestResponse) {} 10 | } 11 | 12 | message ExecTestRequest { 13 | string id = 1; 14 | } 15 | 16 | message ExecTestResponse { 17 | string id = 1; 18 | } 19 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/src/authenticators/authentication.service.ts: -------------------------------------------------------------------------------- 1 | import type { Request } from 'express' 2 | import type { Response } from 'express' 3 | 4 | import { Injectable } from '@nestjs/common' 5 | import { Inject } from '@nestjs/common' 6 | 7 | import { GrpcHttpProxyModuleOptions } from '../module/index.js' 8 | import { GRPC_HTTP_PROXY_MODULE_OPTIONS } from '../module/index.js' 9 | 10 | @Injectable() 11 | export class AuthenticationService { 12 | constructor( 13 | @Inject(GRPC_HTTP_PROXY_MODULE_OPTIONS) private readonly options: GrpcHttpProxyModuleOptions 14 | ) {} 15 | 16 | async authenticate(req: Request, res: Response): Promise { 17 | if (!this.options.authenticator) { 18 | return null 19 | } 20 | 21 | return this.options.authenticator.execute(req, res) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/src/authenticators/authenticator.interface.ts: -------------------------------------------------------------------------------- 1 | import type { Request } from 'express' 2 | import type { Response } from 'express' 3 | 4 | export interface Authenticator { 5 | execute: (req: Request, res: Response) => Promise 6 | } 7 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/src/authenticators/header.authenticator.ts: -------------------------------------------------------------------------------- 1 | import type { Request } from 'express' 2 | 3 | import type { Authenticator } from './authenticator.interface.js' 4 | 5 | export class HeaderAuthenticator implements Authenticator { 6 | async execute(req: Request): Promise { 7 | return req.headers.authorization || null 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/src/authenticators/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './authenticator.interface.js' 2 | export * from './authentication.service.js' 3 | export * from './private-key.authenticator.js' 4 | export * from './header.authenticator.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/src/controllers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-http-proxy.controller.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module/index.js' 2 | export * from './authenticators/index.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/src/module/grpc-http-proxy-module-options.interface.ts: -------------------------------------------------------------------------------- 1 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 2 | import type { Type } from '@nestjs/common/interfaces' 3 | import type { GrpcOptions } from '@nestjs/microservices' 4 | 5 | import type { Authenticator } from '../authenticators/index.js' 6 | 7 | export interface GrpcHttpProxyModuleOptions { 8 | options: GrpcOptions['options'] 9 | authenticator?: Authenticator 10 | } 11 | 12 | export interface GrpcHttpProxyOptionsFactory { 13 | createGrpcHttpProxyOptions: () => GrpcHttpProxyModuleOptions | Promise 14 | } 15 | 16 | export interface GrpcHttpProxyModuleAsyncOptions extends Pick { 17 | useExisting?: Type 18 | useClass?: Type 19 | useFactory?: ( 20 | ...args: Array 21 | ) => GrpcHttpProxyModuleOptions | Promise 22 | inject?: Array 23 | } 24 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/src/module/grpc-http-proxy.constants.ts: -------------------------------------------------------------------------------- 1 | export const GRPC_HTTP_PROXY_MODULE_OPTIONS = 'GRPC_HTTP_PROXY_MODULE_OPTIONS' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/src/module/grpc-http-proxy.providers.ts: -------------------------------------------------------------------------------- 1 | import type { Provider } from '@nestjs/common' 2 | 3 | import type { GrpcHttpProxyModuleOptions } from './grpc-http-proxy-module-options.interface.js' 4 | 5 | import { AuthenticationService } from '../authenticators/index.js' 6 | import { ProtoRegistry } from '../proto/index.js' 7 | import { GRPC_HTTP_PROXY_MODULE_OPTIONS } from './grpc-http-proxy.constants.js' 8 | 9 | export const createGrpcHttpProxyOptionsProvider = ( 10 | options: GrpcHttpProxyModuleOptions 11 | ): Array => [ 12 | { 13 | provide: GRPC_HTTP_PROXY_MODULE_OPTIONS, 14 | useValue: options, 15 | }, 16 | ] 17 | 18 | export const createGrpcHttpProxyProvider = (): Array => [ 19 | ProtoRegistry, 20 | AuthenticationService, 21 | ] 22 | 23 | export const createGrpcHttpProxyExportsProvider = (): Array => [] 24 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './grpc-http-proxy-module-options.interface.js' 2 | export * from './grpc-http-proxy.constants.js' 3 | export * from './grpc-http-proxy.module.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-http-proxy/src/proto/index.ts: -------------------------------------------------------------------------------- 1 | export * from './proto.registry.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## [0.0.13](https://github.com/atls/nestjs/compare/@atls/nestjs-grpc-identity@0.0.12...@atls/nestjs-grpc-identity@0.0.13) (2025-01-24) 4 | 5 | 6 | ### Features 7 | 8 | 9 | * **nestjs:** update grpc reflection ([#341](https://github.com/atls/nestjs/issues/341)) ([3f78e26](https://github.com/atls/nestjs/commit/3f78e26340b9ba64eab425160e8cea7ba83a3538)) 10 | 11 | 12 | 13 | ## 0.0.12 (2025-01-22) 14 | 15 | ### Features 16 | 17 | - **common:** bump yarn, trigger release ([#338](https://github.com/atls/nestjs/issues/338)) ([9837d48](https://github.com/atls/nestjs/commit/9837d482f75928a3ac132d0306ab6de04d8a04b9)) 18 | - **connectrpc:** init ([#339](https://github.com/atls/nestjs/issues/339)) ([663389c](https://github.com/atls/nestjs/commit/663389cd20156a9c10e93d6dbb8326bf8dcac781)) 19 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/integration/src/grpc-identity-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | import { promises as fs } from 'fs' 3 | import { join } from 'path' 4 | 5 | import { GrpcIdentityModule } from '../../src/index.js' 6 | import { TestController } from './test.controller.js' 7 | 8 | @Module({ 9 | imports: [ 10 | GrpcIdentityModule.register({ 11 | jwks: { 12 | jwksUri: join(__dirname, '.jwks.json'), 13 | fetcher: async (jwksUri) => { 14 | const data = await fs.readFile(jwksUri) 15 | 16 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return 17 | return JSON.parse(data.toString()) 18 | }, 19 | cache: true, 20 | jwksRequestsPerMinute: 5, 21 | }, 22 | }), 23 | ], 24 | controllers: [TestController], 25 | }) 26 | export class GrpcIdentityIntegrationModule {} 27 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-identity-integration.module.js' 2 | export * from './proto.options.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/integration/src/proto.options.ts: -------------------------------------------------------------------------------- 1 | import type { GrpcOptions } from '@nestjs/microservices' 2 | 3 | import { Transport } from '@nestjs/microservices' 4 | import path from 'path' 5 | 6 | export const serverOptions: GrpcOptions = { 7 | transport: Transport.GRPC, 8 | options: { 9 | package: ['test'], 10 | protoPath: [path.join(__dirname, './test.proto')], 11 | url: '0.0.0.0:50051', 12 | loader: { 13 | arrays: true, 14 | keepCase: true, 15 | defaults: true, 16 | oneofs: true, 17 | includeDirs: [], 18 | }, 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/integration/src/test.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller } from '@nestjs/common' 2 | import { UseGuards } from '@nestjs/common' 3 | import { GrpcMethod } from '@nestjs/microservices' 4 | 5 | import { GrpcJwtIdentityGuard } from '../../src/index.js' 6 | import { Subject } from '../../src/index.js' 7 | 8 | @Controller() 9 | @UseGuards(GrpcJwtIdentityGuard) 10 | export class TestController { 11 | @GrpcMethod('TestService', 'Test') 12 | test(@Subject() subject: string): { id: string } { 13 | return { 14 | id: subject, 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/integration/src/test.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | service TestService { 6 | rpc Test (ExecTestRequest) returns (ExecTestResponse) {} 7 | } 8 | 9 | message ExecTestRequest { 10 | string id = 1; 11 | } 12 | 13 | message ExecTestResponse { 14 | string id = 1; 15 | } 16 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/config/grpc-identity-env.config.ts: -------------------------------------------------------------------------------- 1 | import type { GrpcIdentityOptionsFactory } from '../module/index.js' 2 | import type { GrpcIdentityModuleOptions } from '../module/index.js' 3 | 4 | import { promises as fs } from 'fs' 5 | 6 | export class GrpcIdentityEnvConfig implements GrpcIdentityOptionsFactory { 7 | getJwksOptions(): GrpcIdentityModuleOptions['jwks'] { 8 | const jwksUri = process.env.IDENTITY_JWKS_URI 9 | 10 | if (!jwksUri) { 11 | throw new Error(`Identity JwksUri configuration not found.`) 12 | } 13 | 14 | const options = { 15 | jwksUri, 16 | rateLimit: true, 17 | cache: true, 18 | } 19 | 20 | if (!jwksUri.startsWith('http')) { 21 | // @ts-expect-error 22 | // eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-argument 23 | options.fetcher = async (uri) => JSON.parse(await fs.readFile(uri, 'utf-8')) 24 | } 25 | 26 | return options 27 | } 28 | 29 | createGrpcIdentityOptions(): GrpcIdentityModuleOptions { 30 | return { 31 | jwks: this.getJwksOptions(), 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-identity-env.config.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './subject.decorator.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/decorators/subject.decorator.ts: -------------------------------------------------------------------------------- 1 | import type { ExecutionContext } from '@nestjs/common' 2 | 3 | import { Metadata } from '@grpc/grpc-js' 4 | import { createParamDecorator } from '@nestjs/common' 5 | 6 | export const Subject = createParamDecorator((data: unknown, context: ExecutionContext) => { 7 | if (context.getType() === 'rpc') { 8 | const metadata = context.getArgByIndex(1) 9 | 10 | if (metadata instanceof Metadata) { 11 | const identityMetadata = metadata.get('identity') 12 | 13 | try { 14 | const identity = JSON.parse(identityMetadata[0].toString()) 15 | 16 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return 17 | return identity.sub 18 | } catch { 19 | return null 20 | } 21 | } 22 | } 23 | 24 | return null 25 | }) 26 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/guards/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-jwt-identity.guard.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './decorators/index.js' 2 | export * from './module/index.js' 3 | export * from './guards/index.js' 4 | export * from './config/index.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/jwt/index.ts: -------------------------------------------------------------------------------- 1 | export * from './jwt.verifier.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/jwt/jwt.verifier.ts: -------------------------------------------------------------------------------- 1 | import type { JwtPayload } from 'jsonwebtoken' 2 | 3 | import { Injectable } from '@nestjs/common' 4 | import { JwksClient } from 'jwks-rsa' 5 | import { decode } from 'jsonwebtoken' 6 | import { verify } from 'jsonwebtoken' 7 | 8 | @Injectable() 9 | export class JwtVerifier { 10 | constructor(private readonly jwksClient: JwksClient) {} 11 | 12 | async verify(token: string): Promise { 13 | try { 14 | const dtoken = decode(token, { complete: true }) 15 | 16 | const key = await this.jwksClient.getSigningKey(dtoken?.header?.kid) 17 | 18 | // @ts-expect-error 19 | // eslint-disable-next-line @typescript-eslint/no-unsafe-argument 20 | const decoded = verify(token, key.publicKey || key.rsaPublicKey) 21 | 22 | if (decoded?.sub) { 23 | return decoded 24 | } 25 | 26 | return null 27 | } catch { 28 | return null 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/module/grpc-identity-module.interface.ts: -------------------------------------------------------------------------------- 1 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 2 | import type { Type } from '@nestjs/common/interfaces' 3 | import type { Options as JwksOptions } from 'jwks-rsa' 4 | 5 | export interface GrpcIdentityModuleOptions { 6 | jwks: JwksOptions 7 | } 8 | 9 | export interface GrpcIdentityOptionsFactory { 10 | createGrpcIdentityOptions: () => GrpcIdentityModuleOptions | Promise 11 | } 12 | 13 | export interface GrpcIdentityModuleAsyncOptions extends Pick { 14 | useExisting?: Type 15 | useClass?: Type 16 | useFactory?: ( 17 | ...args: Array 18 | ) => GrpcIdentityModuleOptions | Promise 19 | inject?: Array 20 | } 21 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/module/grpc-identity.constants.ts: -------------------------------------------------------------------------------- 1 | export const GRPC_IDENTITY_MODULE_OPTIONS = 'GRPC_IDENTITY_MODULE_OPTIONS' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/module/grpc-identity.providers.ts: -------------------------------------------------------------------------------- 1 | import type { Provider } from '@nestjs/common' 2 | 3 | import type { GrpcIdentityModuleOptions } from './grpc-identity-module.interface.js' 4 | 5 | import { JwksClient } from 'jwks-rsa' 6 | 7 | import { JwtVerifier } from '../jwt/index.js' 8 | import { GRPC_IDENTITY_MODULE_OPTIONS } from './grpc-identity.constants.js' 9 | 10 | export const createGrpcIdentityOptionsProvider = ( 11 | options: GrpcIdentityModuleOptions 12 | ): Array => [ 13 | { 14 | provide: GRPC_IDENTITY_MODULE_OPTIONS, 15 | useValue: options, 16 | }, 17 | ] 18 | 19 | export const createGrpcIdentityProvider = (): Array => [] 20 | 21 | export const createGrpcIdentityExportsProvider = (): Array => [ 22 | JwtVerifier, 23 | { 24 | provide: JwksClient, 25 | useFactory: (options: GrpcIdentityModuleOptions) => new JwksClient(options.jwks), 26 | inject: [GRPC_IDENTITY_MODULE_OPTIONS], 27 | }, 28 | ] 29 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-identity/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './grpc-identity-module.interface.js' 2 | export * from './grpc-identity.constants.js' 3 | export * from './grpc-identity.module.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## [0.0.2](https://github.com/atls/nestjs/compare/@atls/grpc-keto@0.0.2...@atls/grpc-keto@0.0.2) (2025-01-24) 4 | 5 | 6 | ### Features 7 | 8 | 9 | * **nestjs:** update grpc reflection ([#341](https://github.com/atls/nestjs/issues/341)) ([3f78e26](https://github.com/atls/nestjs/commit/3f78e26340b9ba64eab425160e8cea7ba83a3538)) 10 | 11 | 12 | 13 | ## 0.0.2 (2025-01-22) 14 | 15 | ### Bug Fixes 16 | 17 | - typecheck, build ([1f9ca05](https://github.com/atls/nestjs/commit/1f9ca0533705c5977ccbfd152a59f545d3f01f1c)) 18 | 19 | ### Features 20 | 21 | - **batch-queue:** init ([6ecbffa](https://github.com/atls/nestjs/commit/6ecbffa3fc54f9bb33ac1ae57b274772b99c8e9d)) 22 | - **common:** bump yarn, trigger release ([#338](https://github.com/atls/nestjs/issues/338)) ([9837d48](https://github.com/atls/nestjs/commit/9837d482f75928a3ac132d0306ab6de04d8a04b9)) 23 | - **connectrpc:** init ([#339](https://github.com/atls/nestjs/issues/339)) ([663389c](https://github.com/atls/nestjs/commit/663389cd20156a9c10e93d6dbb8326bf8dcac781)) 24 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './keto-integration.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/integration/src/keto-integration.controller.ts: -------------------------------------------------------------------------------- 1 | import { UseGuards } from '@nestjs/common' 2 | import { Controller } from '@nestjs/common' 3 | import { Get } from '@nestjs/common' 4 | import { status } from '@grpc/grpc-js' 5 | 6 | import { GuardedByKeto } from '../../src/index.js' 7 | import { KetoGuard } from '../../src/index.js' 8 | 9 | @Controller() 10 | export class KetoIntegrationController { 11 | @Get('/allowed') 12 | async allow(): Promise { 13 | return status.OK 14 | } 15 | 16 | @Get('/protected-by-keto') 17 | @GuardedByKeto((user) => `Group:admin#members@${user}`) 18 | @UseGuards(KetoGuard) 19 | async protect(): Promise { 20 | return status.OK 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/integration/src/keto-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { KetoModule } from '../../src/index.js' 4 | import { KetoIntegrationController } from './keto-integration.controller.js' 5 | 6 | @Module({ 7 | imports: [ 8 | KetoModule.register({ 9 | read: '127.0.0.1:4466', 10 | write: '127.0.0.1:4467', 11 | }), 12 | ], 13 | controllers: [KetoIntegrationController], 14 | }) 15 | export class KetoIntegrationModule {} 16 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/integration/test/keto.yml: -------------------------------------------------------------------------------- 1 | version: v0.11.1-alpha.0 2 | 3 | dsn: memory 4 | 5 | serve: 6 | read: 7 | host: 0.0.0.0 8 | cors: 9 | enabled: false 10 | allow_credentials: true 11 | debug: true 12 | write: 13 | host: 0.0.0.0 14 | cors: 15 | enabled: false 16 | allow_credentials: true 17 | debug: true 18 | 19 | opl: 20 | host: localhost 21 | cors: 22 | enabled: false 23 | allow_credentials: true 24 | debug: true 25 | 26 | namespaces: 27 | location: file:///home/ory/namespaces.keto.ts 28 | 29 | log: 30 | level: debug 31 | format: text 32 | leak_sensitive_values: true 33 | 34 | $schema: file:///config/keto/schema.json 35 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/integration/test/namespaces.keto.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // @ts-ignore 4 | class User implements Namespace {} 5 | 6 | // @ts-ignore 7 | class Group implements Namespace { 8 | related: { 9 | members: User[] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/integration/test/relationships.json: -------------------------------------------------------------------------------- 1 | { 2 | "namespace": "Group", 3 | "object": "admin", 4 | "relation": "members", 5 | "subject_id": "testUser" 6 | } 7 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/decorators/get-guarding-relation.helper.ts: -------------------------------------------------------------------------------- 1 | import type { ReplaceGenerator } from './guarded-by-keto.interfaces.js' 2 | import type { GetGuardingRelationTuple } from './guarded-by-keto.interfaces.js' 3 | 4 | import { GUARDED_BY_METADATA_KEY } from './guarded-by-keto.constants.js' 5 | 6 | export const getGuardingRelationTuple: GetGuardingRelationTuple = (reflector, handler) => 7 | reflector.get( 8 | GUARDED_BY_METADATA_KEY, 9 | handler 10 | ) ?? null 11 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/decorators/guarded-by-keto.constants.ts: -------------------------------------------------------------------------------- 1 | export const GUARDED_BY_METADATA_KEY = Symbol('GuardedByKeto') 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/decorators/guarded-by-keto.decorator.ts: -------------------------------------------------------------------------------- 1 | import type { GuardedByKetoFunction } from './guarded-by-keto.interfaces.js' 2 | 3 | import { SetMetadata } from '@nestjs/common' 4 | 5 | import { GUARDED_BY_METADATA_KEY } from './guarded-by-keto.constants.js' 6 | 7 | export const GuardedByKeto: GuardedByKetoFunction = (relationTuple) => 8 | SetMetadata(GUARDED_BY_METADATA_KEY, relationTuple) 9 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/decorators/guarded-by-keto.interfaces.ts: -------------------------------------------------------------------------------- 1 | import type { CustomDecorator } from '@nestjs/common' 2 | import type { Reflector } from '@nestjs/core' 3 | 4 | export type GetGuardingRelationTuple = ( 5 | reflector: Reflector, 6 | handler: Parameters[1] 7 | ) => ReplaceGenerator | string 8 | 9 | export type ReplaceGenerator = (value: string) => string 10 | 11 | export type GuardedByKetoFunction = ( 12 | relationTuple: ReplaceGenerator | string 13 | ) => CustomDecorator 14 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './guarded-by-keto.decorator.js' 2 | export type { GuardedByKetoFunction } from './guarded-by-keto.interfaces.js' 3 | export type { GetGuardingRelationTuple } from './guarded-by-keto.interfaces.js' 4 | export { GUARDED_BY_METADATA_KEY } from './guarded-by-keto.constants.js' 5 | export { getGuardingRelationTuple } from './get-guarding-relation.helper.js' 6 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/exceptions/exception-message.constants.ts: -------------------------------------------------------------------------------- 1 | export enum KetoExceptionMessage { 2 | GENERAL_ERROR = 'General Keto error', 3 | RELATION_TUPLE_INVALID = 'Provided relation tuple is invalid', 4 | } 5 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/exceptions/general.exception.ts: -------------------------------------------------------------------------------- 1 | import { AssertionError } from 'assert' 2 | 3 | import { KetoExceptionMessage } from './exception-message.constants.js' 4 | 5 | export class KetoGeneralException extends AssertionError { 6 | constructor(message: string) { 7 | super({ message: `${KetoExceptionMessage.GENERAL_ERROR}: ${message}` }) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/exceptions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './general.exception.js' 2 | export * from './relation-tuple-invalid.exception.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/exceptions/relation-tuple-invalid.exception.ts: -------------------------------------------------------------------------------- 1 | import { AssertionError } from 'assert' 2 | 3 | import { KetoExceptionMessage } from './exception-message.constants.js' 4 | 5 | export class KetoRelationTupleInvalidException extends AssertionError { 6 | constructor() { 7 | super({ message: `${KetoExceptionMessage.RELATION_TUPLE_INVALID}` }) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/guard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './keto.guard.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module/index.js' 2 | export * from '@ory/keto-grpc-client' 3 | export * from './guard/index.js' 4 | export * from './decorators/index.js' 5 | export * from './utils/index.js' 6 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export * from './keto.module.js' 2 | export * from './keto.constants.js' 3 | export type * from './keto-module.interfaces.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/module/keto-module.interfaces.ts: -------------------------------------------------------------------------------- 1 | import type { ChannelCredentials } from '@grpc/grpc-js' 2 | import type { Type } from '@nestjs/common/interfaces' 3 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 4 | 5 | export interface KetoModuleOptions { 6 | read: string 7 | write: string 8 | credentials?: ChannelCredentials 9 | global?: boolean 10 | } 11 | 12 | export interface KetoOptionsFactory { 13 | createKetoOptions: () => KetoModuleOptions | Promise 14 | } 15 | 16 | export interface KetoModuleAsyncOptions extends Pick { 17 | useExisting?: Type 18 | useClass?: Type 19 | useFactory?: (...args: Array) => KetoModuleOptions | Promise 20 | inject?: Array 21 | global?: boolean 22 | } 23 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/module/keto.constants.ts: -------------------------------------------------------------------------------- 1 | export const KETO_MODULE_OPTIONS = 'KETO_MODULE_OPTIONS' 2 | export const KETO_READ_CLIENT = 'KETO_READ_CLIENT' 3 | export const KETO_CHECK_CLIENT = 'KETO_CHECK_CLIENT' 4 | export const KETO_WRITE_CLIENT = 'KETO_WRITE_CLIENT' 5 | export const KETO_WRITE_NATIVE_CLIENT = 'KETO_WRITE_NATIVE_CLIENT' 6 | export const KETO_GUARD = 'KETO_GUARD' 7 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './keto-read-client.service.js' 2 | export * from './keto-write-client.service.js' 3 | export * from './keto-check-client.service.js' 4 | export * from './keto-write-native-client.service.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/services/keto-check-client.service.ts: -------------------------------------------------------------------------------- 1 | import { ChannelCredentials } from '@grpc/grpc-js' 2 | import { Inject } from '@nestjs/common' 3 | import { Injectable } from '@nestjs/common' 4 | // @ts-expect-error 5 | import { CheckServiceClient } from '@ory/keto-grpc-client/ory/keto/relation_tuples/v1alpha2/check_service_grpc_pb' 6 | 7 | import { KetoModuleOptions } from '../module/index.js' 8 | import { KETO_MODULE_OPTIONS } from '../module/index.js' 9 | 10 | @Injectable() 11 | export class KetoCheckClientService extends CheckServiceClient { 12 | constructor(@Inject(KETO_MODULE_OPTIONS) private readonly options: KetoModuleOptions) { 13 | // eslint-disable-next-line @typescript-eslint/no-unsafe-call 14 | super(options.read, options.credentials ?? ChannelCredentials.createInsecure()) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/services/keto-write-native-client.service.ts: -------------------------------------------------------------------------------- 1 | import { ChannelCredentials } from '@grpc/grpc-js' 2 | import { Inject } from '@nestjs/common' 3 | // @ts-expect-error 4 | import { WriteServiceClient } from '@ory/keto-grpc-client/ory/keto/relation_tuples/v1alpha2/write_service_grpc_pb' 5 | 6 | import { KetoModuleOptions } from '../module/index.js' 7 | import { KETO_MODULE_OPTIONS } from '../module/index.js' 8 | 9 | export class KetoWriteNativeClientService extends WriteServiceClient { 10 | constructor(@Inject(KETO_MODULE_OPTIONS) private readonly options: KetoModuleOptions) { 11 | // eslint-disable-next-line @typescript-eslint/no-unsafe-call 12 | super(options.write, options.credentials ?? ChannelCredentials.createInsecure()) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-keto/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './relation-tuple-converter.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-playground/integration/src/grpc-playground-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { GrpcPlaygroundModule } from '../../src/index.js' 4 | 5 | @Module({ 6 | imports: [ 7 | GrpcPlaygroundModule.register({ 8 | options: { 9 | package: [], 10 | protoPath: [], 11 | }, 12 | }), 13 | ], 14 | }) 15 | export class GrpcPlaygroundIntegrationModule {} 16 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-playground/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-playground-integration.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-playground/src/controllers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-playground.controller.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-playground/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module/index.js' 2 | 3 | export { HeaderAuthenticator } from '@atls/nestjs-grpc-http-proxy' 4 | export { PrivateKeyAuthenticator } from '@atls/nestjs-grpc-http-proxy' 5 | export type { Authenticator } from '@atls/nestjs-grpc-http-proxy' 6 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-playground/src/module/grpc-playground-module-options.interface.ts: -------------------------------------------------------------------------------- 1 | import type { Authenticator } from '@atls/nestjs-grpc-http-proxy' 2 | import type { GrpcOptions } from '@nestjs/microservices' 3 | 4 | export interface GrpcPlaygroundModuleOptions { 5 | version?: string 6 | authenticator?: Authenticator 7 | options: GrpcOptions['options'] 8 | } 9 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-playground/src/module/grpc-playground.constants.ts: -------------------------------------------------------------------------------- 1 | export const GRPC_PLAYGROUND_MODULE_OPTIONS = `GRPC_PLAYGROUND_MODULE_OPTIONS` 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-playground/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './grpc-playground-module-options.interface.js' 2 | export * from './grpc-playground.constants.js' 3 | export * from './grpc-playground.module.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | 3 | plugins: 4 | - name: ts_proto 5 | out: src 6 | opt: 7 | - nestJs=true 8 | - addGrpcMetadata=true 9 | - esModuleInterop=true 10 | - importSuffix=.js 11 | - useOptionals=messages 12 | - outputServices=grpc-js 13 | - env=node 14 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | 3 | lint: 4 | use: 5 | - DEFAULT 6 | ignore: 7 | - grpc 8 | 9 | breaking: 10 | use: 11 | - FILE 12 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/integration/src/grpc-reflection-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { GrpcReflectionModule } from '../../src/index.js' 4 | import { serverOptions } from './proto.options.js' 5 | 6 | @Module({ 7 | imports: [GrpcReflectionModule.register(serverOptions.options)], 8 | }) 9 | export class GrpcReflectionIntegrationModule {} 10 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-reflection-integration.module.js' 2 | export * from './proto.options.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/integration/src/proto.options.ts: -------------------------------------------------------------------------------- 1 | import type { GrpcOptions } from '@nestjs/microservices' 2 | 3 | import { Transport } from '@nestjs/microservices' 4 | import path from 'path' 5 | 6 | export const serverOptions: GrpcOptions = { 7 | transport: Transport.GRPC, 8 | options: { 9 | package: ['grpc.reflection.v1', 'test'], 10 | protoPath: [ 11 | path.join(__dirname, '../../proto/grpc/reflection/v1/reflection.proto'), 12 | path.join(__dirname, 'test1_service.proto'), 13 | path.join(__dirname, 'test2_service.proto'), 14 | ], 15 | url: '0.0.0.0:50051', 16 | loader: { 17 | arrays: true, 18 | keepCase: false, 19 | defaults: true, 20 | oneofs: true, 21 | includeDirs: [], 22 | }, 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/integration/src/test.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | message Test { 6 | } 7 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/integration/src/test1_service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | import "test.proto"; 6 | 7 | service Test1Service { 8 | rpc GetTest(Test) returns (Test) {} 9 | } 10 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/integration/src/test2_service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package test; 4 | 5 | import "test.proto"; 6 | 7 | service Test2Service { 8 | rpc GetTest(Test) returns (Test) {} 9 | } 10 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/proto/index.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | Object.defineProperty(exports, '__esModule', { value: true }) 4 | exports.serverReflectionPath = void 0 5 | const path_1 = require('path') 6 | exports.serverReflectionPath = path_1.join(__dirname, './grpc/reflection/v1/reflection.proto') 7 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/proto/index.d.ts: -------------------------------------------------------------------------------- 1 | export declare const serverReflectionPath: any 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/src/controllers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-reflection.controller.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/src/grpc/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc-services.registry.js' 2 | export * from './reflection/v1/reflection.js' 3 | export * from './grpc.reflector.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grpc/index.js' 2 | export * from './module/index.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/src/module/grpc-reflection-module-options.interface.ts: -------------------------------------------------------------------------------- 1 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 2 | import type { Type } from '@nestjs/common/interfaces' 3 | import type { GrpcOptions } from '@nestjs/microservices' 4 | 5 | export type GrpcReflectionModuleOptions = GrpcOptions['options'] 6 | 7 | export interface GrpcReflectionOptionsFactory { 8 | createGrpcReflectionOptions: () => 9 | | GrpcReflectionModuleOptions 10 | | Promise 11 | } 12 | 13 | export interface GrpcReflectionModuleAsyncOptions extends Pick { 14 | useExisting?: Type 15 | useClass?: Type 16 | useFactory?: ( 17 | ...args: Array 18 | ) => GrpcReflectionModuleOptions | Promise 19 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 20 | inject?: Array 21 | } 22 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/src/module/grpc-reflection.constants.ts: -------------------------------------------------------------------------------- 1 | export const GRPC_REFLECTION_MODULE_OPTIONS = 'GRPC_REFLECTION_MODULE_OPTIONS' 2 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/src/module/grpc-reflection.providers.ts: -------------------------------------------------------------------------------- 1 | import type { Provider } from '@nestjs/common' 2 | 3 | import type { GrpcReflectionModuleOptions } from './grpc-reflection-module-options.interface.js' 4 | 5 | import { GrpcServicesRegistry } from '../grpc/index.js' 6 | import { GrpcReflector } from '../grpc/index.js' 7 | import { GRPC_REFLECTION_MODULE_OPTIONS } from './grpc-reflection.constants.js' 8 | 9 | export const createGrpcReflectionOptionsProvider = ( 10 | options: GrpcReflectionModuleOptions 11 | ): Array => [ 12 | { 13 | provide: GRPC_REFLECTION_MODULE_OPTIONS, 14 | useValue: options, 15 | }, 16 | ] 17 | 18 | export const createGrpcReflectionProvider = (): Array => [ 19 | GrpcReflector, 20 | GrpcServicesRegistry, 21 | ] 22 | 23 | export const createGrpcReflectionExportsProvider = (): Array => [] 24 | -------------------------------------------------------------------------------- /packages/nestjs-grpc-reflection/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './grpc-reflection-module-options.interface.js' 2 | export * from './grpc-reflection.constants.js' 3 | export * from './grpc-reflection.module.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-hydra/src/client/index.ts: -------------------------------------------------------------------------------- 1 | import { AdminApi } from '@ory/hydra-client' 2 | 3 | export * from '@ory/hydra-client' 4 | 5 | export class HydraAdminApi extends AdminApi {} 6 | -------------------------------------------------------------------------------- /packages/nestjs-hydra/src/config/hydra-env.config.ts: -------------------------------------------------------------------------------- 1 | import type { HydraOptionsFactory } from '../module/index.js' 2 | import type { HydraModuleOptions } from '../module/index.js' 3 | 4 | export class HydraEnvConfig implements HydraOptionsFactory { 5 | createHydraOptions(): HydraModuleOptions { 6 | if (!process.env.HYDRA_ADMIN_URL) { 7 | throw new Error('HYDRA_ADMIN_URL configuration variable required') 8 | } 9 | 10 | return { 11 | urls: { 12 | admin: process.env.HYDRA_ADMIN_URL, 13 | }, 14 | tls: { 15 | termination: process.env.HYDRA_TLS_TERMINATION !== 'false', 16 | }, 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/nestjs-hydra/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export * from './hydra-env.config.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-hydra/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@ory/hydra-client' 2 | 3 | export * from './config/index.js' 4 | export * from './module/index.js' 5 | export * from './client/index.js' 6 | export * from './utils/index.js' 7 | -------------------------------------------------------------------------------- /packages/nestjs-hydra/src/module/hydra-module-options.interface.ts: -------------------------------------------------------------------------------- 1 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 2 | import type { Type } from '@nestjs/common/interfaces' 3 | 4 | export interface HydraModuleUrlsOptions { 5 | admin: string 6 | } 7 | 8 | export interface HydraModuleTlsOptions { 9 | termination?: boolean 10 | } 11 | 12 | export interface HydraModuleOptions { 13 | urls: HydraModuleUrlsOptions 14 | tls?: HydraModuleTlsOptions 15 | global?: boolean 16 | } 17 | 18 | export interface HydraOptionsFactory { 19 | createHydraOptions: () => HydraModuleOptions | Promise 20 | } 21 | 22 | export interface HydraModuleAsyncOptions extends Pick { 23 | useExisting?: Type 24 | useClass?: Type 25 | useFactory?: (...args: Array) => HydraModuleOptions | Promise 26 | inject?: Array 27 | global?: boolean 28 | } 29 | -------------------------------------------------------------------------------- /packages/nestjs-hydra/src/module/hydra.constants.ts: -------------------------------------------------------------------------------- 1 | export const HYDRA_MODULE_OPTIONS = 'HYDRA_MODULE_OPTIONS' 2 | -------------------------------------------------------------------------------- /packages/nestjs-hydra/src/module/hydra.providers.ts: -------------------------------------------------------------------------------- 1 | import type { Provider } from '@nestjs/common' 2 | 3 | import type { HydraModuleOptions } from './hydra-module-options.interface.js' 4 | 5 | import { Configuration } from '../client/index.js' 6 | import { HydraAdminApi } from '../client/index.js' 7 | import { HYDRA_MODULE_OPTIONS } from './hydra.constants.js' 8 | 9 | export const createHydraOptionsProvider = (options: HydraModuleOptions): Array => [ 10 | { 11 | provide: HYDRA_MODULE_OPTIONS, 12 | useValue: options, 13 | }, 14 | ] 15 | 16 | export const createHydraProvider = (): Array => [] 17 | 18 | export const createHydraExportsProvider = (): Array => [ 19 | { 20 | provide: HydraAdminApi, 21 | // eslint-disable-next-line @typescript-eslint/explicit-function-return-type 22 | useFactory: (config: HydraModuleOptions) => { 23 | const baseOptions = config.tls?.termination 24 | ? { headers: { 'X-Forwarded-Proto': 'https' } } 25 | : {} 26 | 27 | return new HydraAdminApi(new Configuration({ basePath: config.urls.admin, baseOptions })) 28 | }, 29 | inject: [HYDRA_MODULE_OPTIONS], 30 | }, 31 | ] 32 | -------------------------------------------------------------------------------- /packages/nestjs-hydra/src/module/hydra.utils.ts: -------------------------------------------------------------------------------- 1 | import { Inject } from '@nestjs/common' 2 | 3 | import { HYDRA_MODULE_OPTIONS } from './hydra.constants.js' 4 | 5 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type 6 | export const InjectHydraOptions = () => Inject(HYDRA_MODULE_OPTIONS) 7 | -------------------------------------------------------------------------------- /packages/nestjs-hydra/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './hydra-module-options.interface.js' 2 | export * from './hydra.constants.js' 3 | export * from './hydra.module.js' 4 | export * from './hydra.utils.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-hydra/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './state.utils.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-hydra/src/utils/state.utils.ts: -------------------------------------------------------------------------------- 1 | import type { LoginRequest } from '@ory/hydra-client' 2 | 3 | type LoginRequestState = Record 4 | 5 | export const extractLoginRequestState = (body: LoginRequest): LoginRequestState => { 6 | if (!body.request_url) { 7 | return {} 8 | } 9 | 10 | try { 11 | const requestUrl = new URL(body.request_url) 12 | 13 | const state = requestUrl.searchParams.get('state') 14 | 15 | if (!state) { 16 | return {} 17 | } 18 | 19 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return 20 | return JSON.parse(Buffer.from(state, 'base64').toString('utf8')) 21 | } catch { 22 | // TODO: log error 23 | 24 | return {} 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/nestjs-kafka/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@atls/nestjs-kafka", 3 | "version": "0.0.2", 4 | "license": "BSD-3-Clause", 5 | "type": "module", 6 | "exports": { 7 | "./package.json": "./package.json", 8 | ".": "./src/index.ts" 9 | }, 10 | "main": "src/index.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "build": "yarn library build", 16 | "prepack": "yarn run build", 17 | "postpack": "rm -rf dist" 18 | }, 19 | "dependencies": { 20 | "@atls/logger": "^0.0.2", 21 | "camelcase": "^8.0.0", 22 | "kafkajs": "^2.2.4" 23 | }, 24 | "devDependencies": { 25 | "@nestjs/common": "^10.0.5", 26 | "@nestjs/core": "^10.0.5", 27 | "reflect-metadata": "^0.1.13", 28 | "rxjs": "^7.8.1" 29 | }, 30 | "peerDependencies": { 31 | "@nestjs/common": "^10", 32 | "@nestjs/core": "^10", 33 | "reflect-metadata": "^0.1", 34 | "rxjs": "^7" 35 | }, 36 | "publishConfig": { 37 | "exports": { 38 | "./package.json": "./package.json", 39 | ".": { 40 | "import": "./dist/index.js", 41 | "types": "./dist/index.d.ts", 42 | "default": "./dist/index.js" 43 | } 44 | }, 45 | "main": "dist/index.js", 46 | "typings": "dist/index.d.ts" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/nestjs-kafka/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from 'kafkajs' 2 | 3 | export * from './module/index.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-kafka/src/logger/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kafka-log.creator.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-kafka/src/logger/kafka-log.creator.ts: -------------------------------------------------------------------------------- 1 | import type { LogEntry } from 'kafkajs' 2 | 3 | import { Logger } from '@atls/logger' 4 | import { logLevel } from 'kafkajs' 5 | import camelcase from 'camelcase' 6 | 7 | export const kafkaLogCreator = (): ((logEntry: LogEntry) => void) => { 8 | const kafkaLogger = new Logger('kafka') 9 | 10 | return ({ namespace, level, log: { message, ...extra } }: LogEntry): void => { 11 | const logger = namespace 12 | ? kafkaLogger.child(camelcase(namespace, { pascalCase: true })) 13 | : kafkaLogger 14 | 15 | if (level === logLevel.ERROR || level === logLevel.NOTHING) { 16 | logger.error(message, extra) 17 | } else if (level === logLevel.WARN) { 18 | logger.warn(message, extra) 19 | } else if (level === logLevel.INFO) { 20 | logger.info(message, extra) 21 | } else if (level === logLevel.DEBUG) { 22 | logger.debug(message, extra) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/nestjs-kafka/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kafka.module.constants.js' 2 | export * from './kafka.config-factory.js' 3 | export * from './kafka.factory.js' 4 | export * from './kafka.module.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-kafka/src/module/kafka.config-factory.ts: -------------------------------------------------------------------------------- 1 | import type { KafkaConfig } from 'kafkajs' 2 | 3 | import { Inject } from '@nestjs/common' 4 | import { Injectable } from '@nestjs/common' 5 | 6 | import { KAFKA_MODULE_OPTIONS_CLIENT_ID } from './kafka.module.constants.js' 7 | import { KAFKA_MODULE_OPTIONS_BROKERS } from './kafka.module.constants.js' 8 | 9 | @Injectable() 10 | export class KafkaConfigFactory { 11 | constructor( 12 | @Inject(KAFKA_MODULE_OPTIONS_CLIENT_ID) 13 | private readonly clientId: string, 14 | @Inject(KAFKA_MODULE_OPTIONS_BROKERS) 15 | private readonly brokers: Array 16 | ) {} 17 | 18 | createKafkaOptions(): KafkaConfig { 19 | return { 20 | clientId: this.clientId || process.env.KAFKA_CLIENT_ID, 21 | brokers: 22 | this.brokers || 23 | (process.env.KAFKA_BROKERS ? process.env.KAFKA_BROKERS.split(',') : ['localhost:29092']), 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/nestjs-kafka/src/module/kafka.factory.ts: -------------------------------------------------------------------------------- 1 | import type { KafkaConfig } from 'kafkajs' 2 | 3 | import { Injectable } from '@nestjs/common' 4 | import { Kafka } from 'kafkajs' 5 | 6 | import { KafkaConfigFactory } from './kafka.config-factory.js' 7 | import { kafkaLogCreator } from '../logger/index.js' 8 | 9 | @Injectable() 10 | export class KafkaFactory { 11 | constructor(private readonly configFactory: KafkaConfigFactory) {} 12 | 13 | create(options: Partial = {}): Kafka { 14 | return new Kafka({ 15 | logCreator: kafkaLogCreator, 16 | ...this.configFactory.createKafkaOptions(), 17 | ...options, 18 | }) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/nestjs-kafka/src/module/kafka.module.constants.ts: -------------------------------------------------------------------------------- 1 | export const KAFKA_MODULE_OPTIONS_GROUP_ID = Symbol('kafka-module-options-group-id') 2 | export const KAFKA_MODULE_OPTIONS_CLIENT_ID = Symbol('kafka-module-options-client-id') 3 | export const KAFKA_MODULE_OPTIONS_BROKERS = Symbol('kafka-module-options-brokers') 4 | -------------------------------------------------------------------------------- /packages/nestjs-kafka/src/module/kafka.module.ts: -------------------------------------------------------------------------------- 1 | import type { DynamicModule } from '@nestjs/common' 2 | import type { KafkaConfig } from 'kafkajs' 3 | 4 | import { Module } from '@nestjs/common' 5 | 6 | import { KafkaConfigFactory } from './kafka.config-factory.js' 7 | import { KafkaFactory } from './kafka.factory.js' 8 | import { KAFKA_MODULE_OPTIONS_CLIENT_ID } from './kafka.module.constants.js' 9 | import { KAFKA_MODULE_OPTIONS_BROKERS } from './kafka.module.constants.js' 10 | 11 | @Module({}) 12 | export class KafkaModule { 13 | static register(options: Partial = {}): DynamicModule { 14 | return { 15 | module: KafkaModule, 16 | providers: [ 17 | KafkaConfigFactory, 18 | KafkaFactory, 19 | { 20 | provide: KAFKA_MODULE_OPTIONS_BROKERS, 21 | useValue: options.brokers, 22 | }, 23 | { 24 | provide: KAFKA_MODULE_OPTIONS_CLIENT_ID, 25 | useValue: options.clientId, 26 | }, 27 | ], 28 | exports: [KafkaConfigFactory, KafkaFactory], 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/nestjs-keto/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './keto-integration.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-keto/integration/src/keto-integration.controller.ts: -------------------------------------------------------------------------------- 1 | import { UseGuards } from '@nestjs/common' 2 | import { Controller } from '@nestjs/common' 3 | import { Get } from '@nestjs/common' 4 | 5 | import { GuardedByKeto } from '../../src/index.js' 6 | import { KetoGuard } from '../../src/index.js' 7 | 8 | @Controller() 9 | export class KetoIntegrationController { 10 | @Get('/allowed') 11 | async allow(): Promise { 12 | return true 13 | } 14 | 15 | @Get('/protected-by-keto') 16 | @GuardedByKeto((user) => `Group:admin#members@${user}`) 17 | @UseGuards(KetoGuard) 18 | async protect(): Promise { 19 | return true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/nestjs-keto/integration/src/keto-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { KetoModule } from '../../src/index.js' 4 | import { KetoIntegrationController } from './keto-integration.controller.js' 5 | 6 | @Module({ 7 | imports: [ 8 | KetoModule.register({ 9 | basePath: '127.0.0.1:4466', 10 | }), 11 | ], 12 | controllers: [KetoIntegrationController], 13 | }) 14 | export class KetoIntegrationModule {} 15 | -------------------------------------------------------------------------------- /packages/nestjs-keto/integration/test/keto.yml: -------------------------------------------------------------------------------- 1 | version: v0.11.1-alpha.0 2 | 3 | dsn: memory 4 | 5 | serve: 6 | read: 7 | host: 0.0.0.0 8 | cors: 9 | enabled: false 10 | allow_credentials: true 11 | debug: true 12 | write: 13 | host: 0.0.0.0 14 | cors: 15 | enabled: false 16 | allow_credentials: true 17 | debug: true 18 | 19 | opl: 20 | host: localhost 21 | cors: 22 | enabled: false 23 | allow_credentials: true 24 | debug: true 25 | 26 | namespaces: 27 | location: file:///home/ory/namespaces.keto.ts 28 | 29 | log: 30 | level: debug 31 | format: text 32 | leak_sensitive_values: true 33 | 34 | $schema: file:///config/keto/schema.json 35 | -------------------------------------------------------------------------------- /packages/nestjs-keto/integration/test/namespaces.keto.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // @ts-ignore 4 | class User implements Namespace {} 5 | 6 | // @ts-ignore 7 | class Group implements Namespace { 8 | related: { 9 | members: User[] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/nestjs-keto/integration/test/relationships.json: -------------------------------------------------------------------------------- 1 | { 2 | "namespace": "Group", 3 | "object": "admin", 4 | "relation": "members", 5 | "subject_id": "testUser" 6 | } 7 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/decorators/get-guarding-relation.helper.ts: -------------------------------------------------------------------------------- 1 | import type { ReplaceGenerator } from './guarded-by-keto.interfaces.js' 2 | import type { GetGuardingRelationTuple } from './guarded-by-keto.interfaces.js' 3 | 4 | import { GUARDED_BY_METADATA_KEY } from './guarded-by-keto.constants.js' 5 | 6 | export const getGuardingRelationTuple: GetGuardingRelationTuple = (reflector, handler) => 7 | reflector.get( 8 | GUARDED_BY_METADATA_KEY, 9 | handler 10 | ) ?? null 11 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/decorators/guarded-by-keto.constants.ts: -------------------------------------------------------------------------------- 1 | export const GUARDED_BY_METADATA_KEY = Symbol('GuardedByKeto') 2 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/decorators/guarded-by-keto.decorator.ts: -------------------------------------------------------------------------------- 1 | import type { GuardedByKetoFunction } from './guarded-by-keto.interfaces.js' 2 | 3 | import { SetMetadata } from '@nestjs/common' 4 | 5 | import { GUARDED_BY_METADATA_KEY } from './guarded-by-keto.constants.js' 6 | 7 | export const GuardedByKeto: GuardedByKetoFunction = (relationTuple) => 8 | SetMetadata(GUARDED_BY_METADATA_KEY, relationTuple) 9 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/decorators/guarded-by-keto.interfaces.ts: -------------------------------------------------------------------------------- 1 | import type { CustomDecorator } from '@nestjs/common' 2 | import type { Reflector } from '@nestjs/core' 3 | 4 | export type GetGuardingRelationTuple = ( 5 | reflector: Reflector, 6 | handler: Parameters[1] 7 | ) => ReplaceGenerator | string 8 | 9 | export type ReplaceGenerator = (value: string) => string 10 | 11 | export type GuardedByKetoFunction = ( 12 | relationTuple: ReplaceGenerator | string 13 | ) => CustomDecorator 14 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './guarded-by-keto.decorator.js' 2 | export type { GuardedByKetoFunction } from './guarded-by-keto.interfaces.js' 3 | export type { GetGuardingRelationTuple } from './guarded-by-keto.interfaces.js' 4 | export { GUARDED_BY_METADATA_KEY } from './guarded-by-keto.constants.js' 5 | export { getGuardingRelationTuple } from './get-guarding-relation.helper.js' 6 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/exceptions/exception-message.constants.ts: -------------------------------------------------------------------------------- 1 | export enum KetoExceptionMessage { 2 | GENERAL_ERROR = 'General Keto error', 3 | RELATION_TUPLE_INVALID = 'Provided relation tuple is invalid', 4 | } 5 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/exceptions/general.exception.ts: -------------------------------------------------------------------------------- 1 | import { AssertionError } from 'node:assert' 2 | 3 | import { KetoExceptionMessage } from './exception-message.constants.js' 4 | 5 | export class KetoGeneralException extends AssertionError { 6 | constructor(message: string) { 7 | super({ message: `${KetoExceptionMessage.GENERAL_ERROR}: ${message}` }) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/exceptions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './general.exception.js' 2 | export * from './relation-tuple-invalid.exception.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/exceptions/relation-tuple-invalid.exception.ts: -------------------------------------------------------------------------------- 1 | import { AssertionError } from 'node:assert' 2 | 3 | import { KetoExceptionMessage } from './exception-message.constants.js' 4 | 5 | export class KetoRelationTupleInvalidException extends AssertionError { 6 | constructor() { 7 | super({ message: `${KetoExceptionMessage.RELATION_TUPLE_INVALID}` }) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/guards/index.ts: -------------------------------------------------------------------------------- 1 | export * from './keto.guard.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module/index.js' 2 | export * from '@ory/keto-client' 3 | export * from './guards/index.js' 4 | export * from './decorators/index.js' 5 | export * from './utils/index.js' 6 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export * from './keto.module.js' 2 | export * from './keto.constants.js' 3 | export type * from './keto-module.interfaces.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/module/keto.constants.ts: -------------------------------------------------------------------------------- 1 | export const KETO_MODULE_CONFIGURATION = 'KETO_MODULE_CONFIGURATION' 2 | export const KETO_READ_CLIENT = 'KETO_READ_CLIENT' 3 | export const KETO_PERMISSIONS = 'KETO_PERMISSIONS' 4 | export const KETO_WRITE_CLIENT = 'KETO_WRITE_CLIENT' 5 | export const KETO_RELATIONS = 'KETO_RELATIONS' 6 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './keto-read-client.service.js' 2 | export * from './keto-write-client.service.js' 3 | export * from './keto-configuration.service.js' 4 | export * from './keto-permissions.service.js' 5 | export * from './keto-relations.service.js' 6 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/services/keto-configuration.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject } from '@nestjs/common' 2 | import { Injectable } from '@nestjs/common' 3 | import { ConfigurationParameters } from '@ory/keto-client' 4 | import { Configuration } from '@ory/keto-client' 5 | 6 | import { KETO_MODULE_CONFIGURATION } from '../module/index.js' 7 | 8 | @Injectable() 9 | export class KetoConfigurationService extends Configuration { 10 | constructor( 11 | @Inject(KETO_MODULE_CONFIGURATION) private readonly options: ConfigurationParameters 12 | ) { 13 | super(options) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/services/keto-permissions.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject } from '@nestjs/common' 2 | import { Injectable } from '@nestjs/common' 3 | import { PermissionApi } from '@ory/keto-client' 4 | 5 | import { KETO_MODULE_CONFIGURATION } from '../module/index.js' 6 | import { KetoConfigurationService } from './keto-configuration.service.js' 7 | 8 | @Injectable() 9 | export class KetoPermissionsService extends PermissionApi { 10 | constructor(@Inject(KETO_MODULE_CONFIGURATION) readonly configuration: KetoConfigurationService) { 11 | super(configuration) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/services/keto-relations.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject } from '@nestjs/common' 2 | import { Injectable } from '@nestjs/common' 3 | import { RelationshipApi } from '@ory/keto-client' 4 | import { Configuration } from '@ory/keto-client' 5 | 6 | import { KETO_MODULE_CONFIGURATION } from '../module/index.js' 7 | 8 | @Injectable() 9 | export class KetoRelationsService extends RelationshipApi { 10 | constructor(@Inject(KETO_MODULE_CONFIGURATION) private readonly options: Configuration) { 11 | super(options) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/nestjs-keto/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './relation-tuple-converter.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kratos-integration.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/integration/src/kratos-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | 3 | import { KratosModule } from '../../src/index.js' 4 | import { RedirectController } from './redirect.controller.js' 5 | import { SelfServiceController } from './self-service.controller.js' 6 | import { SessionController } from './session.controller.js' 7 | 8 | @Module({ 9 | imports: [ 10 | KratosModule.register({ 11 | browser: 'http://localhost:3000', 12 | public: 'http://localhost:3000', 13 | }), 14 | ], 15 | controllers: [RedirectController, SelfServiceController, SessionController], 16 | }) 17 | export class KratosIntegrationModule {} 18 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/integration/src/self-service.controller.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-empty-function */ 2 | 3 | import { Controller } from '@nestjs/common' 4 | import { Get } from '@nestjs/common' 5 | import { HttpCode } from '@nestjs/common' 6 | import { Res } from '@nestjs/common' 7 | import { Headers } from '@nestjs/common' 8 | import { Response } from 'express' 9 | 10 | @Controller() 11 | export class SelfServiceController { 12 | @Get('/self-service/login/flows') 13 | @HttpCode(403) 14 | login(): void {} 15 | 16 | @Get('/self-service/registration/flows') 17 | @HttpCode(404) 18 | registration(): void {} 19 | 20 | @Get('/self-service/recovery/flows') 21 | @HttpCode(410) 22 | recovery(): void {} 23 | 24 | @Get('/sessions/whoami') 25 | whoami(@Res() res: Response, @Headers('Cookie') cookie?: string): void { 26 | if (cookie) { 27 | res.status(200).json({ 28 | id: 'test', 29 | }) 30 | } else { 31 | res.status(401).send() 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/integration/src/session.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller } from '@nestjs/common' 2 | import { Get } from '@nestjs/common' 3 | 4 | import { Session } from '../../src/index.js' 5 | import { Whoami } from '../../src/index.js' 6 | 7 | @Controller() 8 | export class SessionController { 9 | @Get('/identity/session/whoami') 10 | // eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types 11 | async whoami(@Whoami() identity: Session) { 12 | return identity 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/client/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@ory/kratos-client' 2 | 3 | export * from './kratos-public.api.js' 4 | export * from './kratos-admin.api.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/client/kratos-admin.api.ts: -------------------------------------------------------------------------------- 1 | import { IdentityApi } from '@ory/kratos-client' 2 | 3 | export class KratosAdminApi extends IdentityApi {} 4 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/client/kratos-public.api.ts: -------------------------------------------------------------------------------- 1 | import { FrontendApi } from '@ory/kratos-client' 2 | 3 | export class KratosPublicApi extends FrontendApi {} 4 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kratos-env.config.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/config/kratos-env.config.ts: -------------------------------------------------------------------------------- 1 | import type { KratosOptionsFactory } from '../module/index.js' 2 | import type { KratosModuleOptions } from '../module/index.js' 3 | 4 | export class KratosEnvConfig implements KratosOptionsFactory { 5 | createKratosOptions(): KratosModuleOptions { 6 | if (!process.env.KRATOS_BROWSER_URL) { 7 | throw new Error('KRATOS_BROWSER_URL configuration variable required') 8 | } 9 | 10 | if (!process.env.PUBLIC_BROWSER_URL) { 11 | throw new Error('PUBLIC_BROWSER_URL configuration variable required') 12 | } 13 | 14 | return { 15 | browser: process.env.KRATOS_BROWSER_URL, 16 | public: process.env.PUBLIC_BROWSER_URL, 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/decorators/flow.decorator.ts: -------------------------------------------------------------------------------- 1 | import type { ExecutionContext } from '@nestjs/common' 2 | 3 | import { createParamDecorator } from '@nestjs/common' 4 | 5 | import { KratosFlowRequiredException } from '../exceptions/index.js' 6 | 7 | export const Flow = createParamDecorator((data: unknown, ctx: ExecutionContext) => { 8 | const request = ctx.switchToHttp().getRequest() 9 | 10 | if (!request.query.flow) { 11 | throw new KratosFlowRequiredException() 12 | } 13 | 14 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return 15 | return request.query.flow 16 | }) 17 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './whoami.decorator.js' 2 | export * from './flow.decorator.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/decorators/whoami.decorator.ts: -------------------------------------------------------------------------------- 1 | import type { ExecutionContext } from '@nestjs/common' 2 | 3 | import { createParamDecorator } from '@nestjs/common' 4 | 5 | import { WhoamiPipe } from '../pipes/index.js' 6 | 7 | export const WhoamiCredentials = createParamDecorator(( 8 | data: unknown, 9 | ctx: ExecutionContext 10 | ): [string, string] => { 11 | const request = ctx.switchToHttp().getRequest() 12 | 13 | // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return 14 | return [request.get('cookie'), request.get('authorization')] 15 | }) 16 | 17 | export const Whoami = (): ReturnType => WhoamiCredentials(WhoamiPipe) 18 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/exceptions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kratos-redirect-required.exception.js' 2 | export * from './kratos-flow-required.exception.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/exceptions/kratos-flow-required.exception.ts: -------------------------------------------------------------------------------- 1 | export class KratosFlowRequiredException extends Error { 2 | constructor() { 3 | super('Kratos flow required') 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/exceptions/kratos-redirect-required.exception.ts: -------------------------------------------------------------------------------- 1 | import type { KratosBrowserUrlFlow } from '../urls/index.js' 2 | 3 | export class KratosRedirectRequiredException extends Error { 4 | constructor(public readonly redirectTo: KratosBrowserUrlFlow) { 5 | super('Kratos redirect required') 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/filters/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kratos-expection.filter.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@ory/kratos-client' 2 | 3 | export * from './interceptors/index.js' 4 | export * from './exceptions/index.js' 5 | export * from './decorators/index.js' 6 | export * from './filters/index.js' 7 | export * from './module/index.js' 8 | export * from './config/index.js' 9 | export * from './client/index.js' 10 | export * from './pipes/index.js' 11 | export * from './utils/index.js' 12 | export * from './urls/index.js' 13 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/interceptors/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kratos-redirect.interceptor.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './kratos-module-options.interface.js' 2 | export * from './kratos.constants.js' 3 | export * from './kratos.module.js' 4 | export * from './kratos.utils.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/module/kratos-module-options.interface.ts: -------------------------------------------------------------------------------- 1 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 2 | import type { Type } from '@nestjs/common/interfaces' 3 | 4 | export interface KratosModuleOptions { 5 | public: string 6 | browser: string 7 | admin?: string 8 | global?: boolean 9 | } 10 | 11 | export interface KratosOptionsFactory { 12 | // eslint-disable-next-line @typescript-eslint/method-signature-style 13 | createKratosOptions(): KratosModuleOptions | Promise 14 | } 15 | 16 | export interface KratosModuleAsyncOptions extends Pick { 17 | useExisting?: Type 18 | useClass?: Type 19 | useFactory?: (...args: Array) => KratosModuleOptions | Promise 20 | inject?: Array 21 | global?: boolean 22 | } 23 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/module/kratos.constants.ts: -------------------------------------------------------------------------------- 1 | export const KRATOS_MODULE_OPTIONS = 'KRATOS_MODULE_OPTIONS' 2 | export const KRATOS_BROWSER_URLS = 'KRATOS_BROWSER_URLS' 3 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/module/kratos.utils.ts: -------------------------------------------------------------------------------- 1 | import { Inject } from '@nestjs/common' 2 | 3 | import { KRATOS_MODULE_OPTIONS } from './kratos.constants.js' 4 | 5 | export const InjectKratosOptions: () => ParameterDecorator = () => Inject(KRATOS_MODULE_OPTIONS) 6 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/pipes/index.ts: -------------------------------------------------------------------------------- 1 | export * from './whoami.pipe.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/pipes/whoami.pipe.ts: -------------------------------------------------------------------------------- 1 | import type { PipeTransform } from '@nestjs/common' 2 | import type { ArgumentMetadata } from '@nestjs/common' 3 | import type { Session } from '@ory/kratos-client' 4 | 5 | import { Injectable } from '@nestjs/common' 6 | 7 | import { KratosPublicApi } from '../client/index.js' 8 | 9 | @Injectable() 10 | export class WhoamiPipe implements PipeTransform { 11 | constructor(private readonly kratos: KratosPublicApi) {} 12 | 13 | public async transform( 14 | value: Array, 15 | metadata: ArgumentMetadata 16 | ): Promise { 17 | try { 18 | const { data } = await this.kratos.toSession({ cookie: value[0] }) 19 | 20 | return data 21 | } catch { 22 | // TODO: Handle errors 23 | 24 | return null 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/urls/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kratos-browser.urls.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './method-config.util.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-kratos/src/utils/method-config.util.ts: -------------------------------------------------------------------------------- 1 | import type { LoginFlow } from '@ory/kratos-client' 2 | import type { RecoveryFlow } from '@ory/kratos-client' 3 | import type { RegistrationFlow } from '@ory/kratos-client' 4 | import type { SettingsFlow } from '@ory/kratos-client' 5 | import type { VerificationFlow } from '@ory/kratos-client' 6 | import type { UiContainer } from '@ory/kratos-client' 7 | 8 | export type MethodConfigFlow = 9 | | LoginFlow 10 | | RecoveryFlow 11 | | RegistrationFlow 12 | | SettingsFlow 13 | | VerificationFlow 14 | 15 | export type MethodConfig = UiContainer 16 | 17 | export const methodConfig = (flow: MethodConfigFlow, key: string): MethodConfig | null => { 18 | if (flow.active && flow.active !== key) return null 19 | 20 | if (!flow.ui) return null 21 | 22 | return flow.ui 23 | } 24 | -------------------------------------------------------------------------------- /packages/nestjs-logger/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './logger/index.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-logger/src/logger/index.ts: -------------------------------------------------------------------------------- 1 | export * from './nest.logger.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-microservices-registry/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 0.0.1 (2025-03-15) 4 | 5 | 6 | ### Bug Fixes 7 | 8 | 9 | * **nestjs-microservices-registry:** release ([d5daec7](https://github.com/atls/nestjs/commit/d5daec7bc06379fb2f16afc29d7c2a8d2548d5d2)) 10 | 11 | ### Features 12 | 13 | 14 | * **nestjs-microservices-registry:** init ([490e6a5](https://github.com/atls/nestjs/commit/490e6a5ddf60ec1cd904dccab5dad94e554fc769)) 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/nestjs-microservices-registry/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './registry/index.js' 2 | export * from './module/index.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-microservices-registry/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export * from './microservices-registry.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-microservices-registry/src/registry/index.ts: -------------------------------------------------------------------------------- 1 | export * from './microservices.registry.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-microservices-registry/src/registry/microservices.registry.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ 2 | 3 | import type { INestApplication } from '@nestjs/common' 4 | import type { NestHybridApplicationOptions } from '@nestjs/common' 5 | 6 | export class MicroservisesRegistry { 7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 8 | static #instances: Set = new Set() 9 | 10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 11 | public static add(options: any): void { 12 | this.#instances.add(options) 13 | } 14 | 15 | public static connect( 16 | app: INestApplication, 17 | hybridAppOptions: NestHybridApplicationOptions = {} 18 | ): void { 19 | this.#instances.forEach((options) => app.connectMicroservice(options, hybridAppOptions)) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-config/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 0.0.1 (2025-03-14) 4 | 5 | 6 | ### Features 7 | 8 | 9 | * **nestjs:** init ([b6d0be1](https://github.com/atls/nestjs/commit/b6d0be197b5d38325fc01caa2b3f08e21d9d6816)) 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-config/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module/index.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-config/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './mikro-orm-config.module.interfaces.js' 2 | 3 | export * from './mikro-orm-config.module.constants.js' 4 | export * from './mikro-orm.config-builder.js' 5 | export * from './mikro-orm-config.module.js' 6 | export * from './mikro-orm.config.js' 7 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-config/src/module/mikro-orm-config.module.constants.ts: -------------------------------------------------------------------------------- 1 | export const MIKRO_ORM_CONFIG_MODULE_OPTIONS = Symbol('mikro-orm-config-module-options') 2 | export const MIKRO_ORM_CONFIG_MODULE_OPTIONS_PORT = Symbol('mikro-orm-config-module-options-port') 3 | export const MIKRO_ORM_CONFIG_MODULE_OPTIONS_HOST = Symbol('mikro-orm-config-module-options-host') 4 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-config/src/module/mikro-orm-config.module.interfaces.ts: -------------------------------------------------------------------------------- 1 | import type { AnyEntity } from '@mikro-orm/core' 2 | import type { EntityName } from '@mikro-orm/core' 3 | import type { MigrationObject } from '@mikro-orm/core' 4 | import type { Options } from '@mikro-orm/core' 5 | 6 | export interface MikroORMConfigOptions { 7 | driver: Options['driver'] 8 | 9 | port?: number 10 | host?: string 11 | database?: string 12 | username?: string 13 | password?: string 14 | 15 | entities?: Array> | Record> 16 | 17 | migrationsList?: Array | Record 18 | 19 | migrationsTableName?: string 20 | 21 | debug?: boolean 22 | } 23 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-config/src/module/mikro-orm.config-builder.ts: -------------------------------------------------------------------------------- 1 | import type { LoggerOptions } from '@mikro-orm/core' 2 | import type { MikroOrmModuleOptions } from '@mikro-orm/nestjs' 3 | 4 | import { Logger } from '@atls/logger' 5 | import { MikroORMLogger } from '@atls/mikro-orm-logger' 6 | 7 | export class MikroORMConfigBuilder { 8 | static build(options: Partial): MikroOrmModuleOptions { 9 | return { 10 | driver: options.driver, 11 | port: options.port || 5432, 12 | host: options.host || process.env.DB_HOST || 'localhost', 13 | dbName: options.dbName || process.env.DB_DATABASE || 'db', 14 | user: options.user || process.env.DB_USERNAME || 'postgres', 15 | password: options.password || process.env.DB_PASSWORD || 'password', 16 | debug: options.debug || Boolean(process.env.DB_DEBUG) || false, 17 | migrations: options.migrations, 18 | entities: options.entities, 19 | forceUndefined: true, 20 | 21 | loggerFactory: (opts: LoggerOptions): MikroORMLogger => new MikroORMLogger(opts), 22 | logger: (message: string): void => { 23 | new Logger('mikro-orm:migrations').info(message) 24 | }, 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-request-context/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 0.0.1 (2025-03-14) 4 | 5 | 6 | ### Features 7 | 8 | 9 | * **nestjs-mikro-orm-request-context:** init ([c2a2388](https://github.com/atls/nestjs/commit/c2a2388d6b01ddef65b0c85cd1510816f8880b34)) 10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-request-context/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@atls/nestjs-mikro-orm-request-context", 3 | "version": "0.0.1", 4 | "license": "BSD-3-Clause", 5 | "type": "module", 6 | "exports": { 7 | "./package.json": "./package.json", 8 | ".": "./src/index.ts" 9 | }, 10 | "main": "src/index.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "build": "yarn library build", 16 | "prepack": "yarn run build", 17 | "postpack": "rm -rf dist" 18 | }, 19 | "devDependencies": { 20 | "@mikro-orm/core": "5.7.12", 21 | "@nestjs/common": "10.0.5", 22 | "@nestjs/core": "10.0.5", 23 | "reflect-metadata": "0.2.2", 24 | "rxjs": "7.8.1" 25 | }, 26 | "peerDependencies": { 27 | "@mikro-orm/core": "^5", 28 | "@nestjs/common": "^10", 29 | "@nestjs/core": "^10", 30 | "reflect-metadata": "^0.2", 31 | "rxjs": "^7" 32 | }, 33 | "publishConfig": { 34 | "exports": { 35 | "./package.json": "./package.json", 36 | ".": { 37 | "import": "./dist/index.js", 38 | "types": "./dist/index.d.ts", 39 | "default": "./dist/index.js" 40 | } 41 | }, 42 | "main": "dist/index.js", 43 | "typings": "dist/index.d.ts" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-request-context/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './interceptors/index.js' 2 | export * from './module/index.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-request-context/src/interceptors/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mikro-orm-request-context.interceptor.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-request-context/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mikro-orm-request-context.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-mikro-orm-request-context/src/module/mikro-orm-request-context.module.ts: -------------------------------------------------------------------------------- 1 | import type { DynamicModule } from '@nestjs/common' 2 | 3 | import { MikroORM } from '@mikro-orm/core' 4 | import { Module } from '@nestjs/common' 5 | import { APP_INTERCEPTOR } from '@nestjs/core' 6 | 7 | import { MikroORMRequestContextInterceptor } from '../interceptors/index.js' 8 | 9 | @Module({}) 10 | export class MikroORMRequestContextModule { 11 | static forInterceptor(options = {}): DynamicModule { 12 | return { 13 | ...options, 14 | module: MikroORMRequestContextModule, 15 | providers: [ 16 | { 17 | provide: APP_INTERCEPTOR, 18 | useFactory: (orm: MikroORM) => new MikroORMRequestContextInterceptor(orm), 19 | inject: [MikroORM], 20 | }, 21 | ], 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/nestjs-proto-types/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## [0.0.11](https://github.com/atls/nestjs/compare/@atls/nestjs-proto-types@0.0.10...@atls/nestjs-proto-types@0.0.11) (2025-02-12) 4 | 5 | 6 | 7 | 8 | 9 | 10 | ## [0.0.10](https://github.com/atls/nestjs/compare/@atls/nestjs-proto-types@0.0.8...@atls/nestjs-proto-types@0.0.10) (2025-01-24) 11 | 12 | 13 | 14 | 15 | 16 | 17 | ## 0.0.8 (2025-01-24) 18 | 19 | 20 | ### Bug Fixes 21 | 22 | 23 | * export proto from grpc reflection ([#336](https://github.com/atls/nestjs/issues/336)) ([1a23fc9](https://github.com/atls/nestjs/commit/1a23fc952483056f248cc983283bb5e320bd92a2)) 24 | 25 | ### Features 26 | 27 | 28 | * **common:** bump yarn, trigger release ([#338](https://github.com/atls/nestjs/issues/338)) ([9837d48](https://github.com/atls/nestjs/commit/9837d482f75928a3ac132d0306ab6de04d8a04b9)) 29 | 30 | 31 | -------------------------------------------------------------------------------- /packages/nestjs-proto-types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@atls/nestjs-proto-types", 3 | "version": "0.0.11", 4 | "license": "BSD-3-Clause", 5 | "type": "module", 6 | "exports": { 7 | "./package.json": "./package.json", 8 | ".": "./src/index.ts" 9 | }, 10 | "main": "src/index.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "build": "yarn library build", 16 | "prepack": "yarn run build", 17 | "postpack": "rm -rf dist" 18 | }, 19 | "publishConfig": { 20 | "exports": { 21 | "./package.json": "./package.json", 22 | ".": { 23 | "import": "./dist/index.js", 24 | "types": "./dist/index.d.ts", 25 | "default": "./dist/index.js" 26 | } 27 | }, 28 | "main": "dist/index.js", 29 | "typings": "dist/index.d.ts" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/nestjs-proto-types/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Declares a module for `.proto` files, which are commonly used for defining 3 | * Protocol Buffers (protobuf) schemas. 4 | * 5 | * This declaration allows TypeScript to recognize `.proto` files as modules 6 | * that can be imported directly in TypeScript projects, enabling integration 7 | * with Protocol Buffers in environments where `.proto` files are parsed or 8 | * used as source definitions for generating classes and types. 9 | * 10 | * @module 11 | * @typedef {string} ProtoFile - Represents the imported `.proto` file as a string 12 | */ 13 | // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error 14 | // @ts-ignore correct module name 15 | declare module '*.proto' 16 | -------------------------------------------------------------------------------- /packages/nestjs-redis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@atls/nestjs-redis", 3 | "version": "0.0.1", 4 | "license": "BSD-3-Clause", 5 | "type": "module", 6 | "exports": { 7 | "./package.json": "./package.json", 8 | ".": "./src/index.ts" 9 | }, 10 | "main": "src/index.ts", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "build": "yarn library build", 16 | "prepack": "yarn run build", 17 | "postpack": "rm -rf dist" 18 | }, 19 | "dependencies": { 20 | "ioredis": "^5.3.2" 21 | }, 22 | "devDependencies": { 23 | "@nestjs/common": "^10.0.5", 24 | "@nestjs/core": "^10.0.5", 25 | "reflect-metadata": "^0.1.13", 26 | "rxjs": "^7.8.1" 27 | }, 28 | "peerDependencies": { 29 | "@nestjs/common": "^10", 30 | "@nestjs/core": "^10", 31 | "reflect-metadata": "^0.1", 32 | "rxjs": "^7" 33 | }, 34 | "publishConfig": { 35 | "exports": { 36 | "./package.json": "./package.json", 37 | ".": { 38 | "import": "./dist/index.js", 39 | "types": "./dist/index.d.ts", 40 | "default": "./dist/index.js" 41 | } 42 | }, 43 | "main": "dist/index.js", 44 | "typings": "dist/index.d.ts" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/nestjs-redis/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from 'ioredis' 2 | export * from './module/index.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-redis/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export * from './redis.module.constants.js' 2 | export * from './redis.config-factory.js' 3 | export * from './redis.factory.js' 4 | export * from './redis.module.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-redis/src/module/redis.factory.ts: -------------------------------------------------------------------------------- 1 | import type { RedisOptions } from 'ioredis' 2 | 3 | import { Injectable } from '@nestjs/common' 4 | import { Redis } from 'ioredis' 5 | 6 | import { RedisConfigFactory } from './redis.config-factory.js' 7 | 8 | @Injectable() 9 | export class RedisFactory { 10 | constructor(private readonly configFactory: RedisConfigFactory) {} 11 | 12 | create(options: RedisOptions = {}): Redis { 13 | return new Redis({ 14 | ...this.configFactory.createRedisOptions(), 15 | ...options, 16 | }) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/nestjs-redis/src/module/redis.module.constants.ts: -------------------------------------------------------------------------------- 1 | export const REDIS_MODULE_OPTIONS_HOST = Symbol('redis-module-options-host') 2 | export const REDIS_MODULE_OPTIONS_PORT = Symbol('redis-module-options-port') 3 | export const REDIS_MODULE_OPTIONS_USERNAME = Symbol('redis-module-options-username') 4 | export const REDIS_MODULE_OPTIONS_PASSWORD = Symbol('redis-module-options-password') 5 | -------------------------------------------------------------------------------- /packages/nestjs-s3-client/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## [0.0.2](https://github.com/atls/nestjs/compare/@atls/nestjs-s3-client@0.0.1...@atls/nestjs-s3-client@0.0.2) (2025-01-24) 4 | 5 | 6 | ### Features 7 | 8 | 9 | * **nestjs:** update grpc reflection ([#341](https://github.com/atls/nestjs/issues/341)) ([3f78e26](https://github.com/atls/nestjs/commit/3f78e26340b9ba64eab425160e8cea7ba83a3538)) 10 | 11 | 12 | 13 | ## 0.0.1 (2025-01-22) 14 | 15 | ### Features 16 | 17 | - **common:** bump yarn, trigger release ([#338](https://github.com/atls/nestjs/issues/338)) ([9837d48](https://github.com/atls/nestjs/commit/9837d482f75928a3ac132d0306ab6de04d8a04b9)) 18 | - **connectrpc:** init ([#339](https://github.com/atls/nestjs/issues/339)) ([663389c](https://github.com/atls/nestjs/commit/663389cd20156a9c10e93d6dbb8326bf8dcac781)) 19 | - **s3-client:** init package ([65988c4](https://github.com/atls/nestjs/commit/65988c4eeaa194b45dd37e4332baebadc0400586)) 20 | - **yarn:** global cache ([719bbcd](https://github.com/atls/nestjs/commit/719bbcd7bef9f8802b7670b5603c1fdd72009e14)) 21 | -------------------------------------------------------------------------------- /packages/nestjs-s3-client/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@aws-sdk/s3-request-presigner' 2 | export * from '@aws-sdk/client-s3' 3 | 4 | export * from './module/index.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-s3-client/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './s3-client.module.interfaces.js' 2 | export * from './s3-client.module.constants.js' 3 | export * from './s3-client.config-factory.js' 4 | export * from './s3-client.factory.js' 5 | export * from './s3-client.module.js' 6 | -------------------------------------------------------------------------------- /packages/nestjs-s3-client/src/module/s3-client.config-factory.ts: -------------------------------------------------------------------------------- 1 | import type { S3ClientConfig } from '@aws-sdk/client-s3' 2 | 3 | import type { S3ClientModuleOptions } from './s3-client.module.interfaces.js' 4 | 5 | import { Inject } from '@nestjs/common' 6 | import { Injectable } from '@nestjs/common' 7 | import { fromEnv } from '@aws-sdk/credential-providers' 8 | 9 | import { S3_CLIENT_MODULE_OPTIONS } from './s3-client.module.constants.js' 10 | 11 | @Injectable() 12 | export class S3ClientConfigFactory { 13 | constructor( 14 | @Inject(S3_CLIENT_MODULE_OPTIONS) 15 | private readonly options: S3ClientModuleOptions 16 | ) {} 17 | 18 | createS3ClientOptions(options: S3ClientModuleOptions = {}): S3ClientConfig { 19 | return { 20 | endpoint: options.endpoint || this.options.endpoint || process.env.S3_ENDPOINT, 21 | region: options.region || this.options.region || process.env.S3_REGION, 22 | credentials: options.credentials || this.options.credentials || fromEnv(), 23 | forcePathStyle: true, 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/nestjs-s3-client/src/module/s3-client.factory.ts: -------------------------------------------------------------------------------- 1 | import type { S3ClientModuleOptions } from './s3-client.module.interfaces.js' 2 | 3 | import { S3Client } from '@aws-sdk/client-s3' 4 | import { Injectable } from '@nestjs/common' 5 | 6 | import { S3ClientConfigFactory } from './s3-client.config-factory.js' 7 | 8 | @Injectable() 9 | export class S3ClientFactory { 10 | constructor(private readonly configFactory: S3ClientConfigFactory) {} 11 | 12 | create(options: S3ClientModuleOptions = {}): S3Client { 13 | return new S3Client(this.configFactory.createS3ClientOptions(options)) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/nestjs-s3-client/src/module/s3-client.module.constants.ts: -------------------------------------------------------------------------------- 1 | export const S3_CLIENT_MODULE_OPTIONS = Symbol('s3-client-module-options') 2 | -------------------------------------------------------------------------------- /packages/nestjs-s3-client/src/module/s3-client.module.interfaces.ts: -------------------------------------------------------------------------------- 1 | import type { AwsCredentialIdentity } from '@aws-sdk/types' 2 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 3 | import type { Type } from '@nestjs/common/interfaces' 4 | 5 | export interface S3ClientModuleOptions { 6 | endpoint?: string 7 | region?: string 8 | credentials?: AwsCredentialIdentity 9 | } 10 | 11 | export interface S3ClientOptionsFactory { 12 | createS3ClientOptions: () => Promise | S3ClientModuleOptions 13 | } 14 | 15 | export interface S3ClientModuleAsyncOptions extends Pick { 16 | useExisting?: Type 17 | useClass?: Type 18 | useFactory?: (...args: Array) => Promise | S3ClientModuleOptions 19 | inject?: Array 20 | } 21 | -------------------------------------------------------------------------------- /packages/nestjs-signed-url/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## [0.1.45](https://github.com/atls/nestjs/compare/@atlantis-lab/nestjs-signed-url@0.1.44...@atlantis-lab/nestjs-signed-url@0.1.45) (2025-01-24) 4 | 5 | 6 | ### Features 7 | 8 | 9 | * **nestjs:** update grpc reflection ([#341](https://github.com/atls/nestjs/issues/341)) ([3f78e26](https://github.com/atls/nestjs/commit/3f78e26340b9ba64eab425160e8cea7ba83a3538)) 10 | 11 | 12 | 13 | ## 0.1.44 (2025-01-22) 14 | 15 | ### Features 16 | 17 | - **common:** bump yarn, trigger release ([#338](https://github.com/atls/nestjs/issues/338)) ([9837d48](https://github.com/atls/nestjs/commit/9837d482f75928a3ac132d0306ab6de04d8a04b9)) 18 | - **connectrpc:** init ([#339](https://github.com/atls/nestjs/issues/339)) ([663389c](https://github.com/atls/nestjs/commit/663389cd20156a9c10e93d6dbb8326bf8dcac781)) 19 | - **nestjs-signed-url:** cover signed url service handlers with tests ([aa829c1](https://github.com/atls/nestjs/commit/aa829c173bb90f1e4ca5781a7d389a0e7ba1bec0)), closes [#159](https://github.com/atls/nestjs/issues/159) 20 | - **nestjs-signed-url:** init ([2c0380d](https://github.com/atls/nestjs/commit/2c0380dd5c8950a7a8e4f4b01a57350f2100490a)) 21 | -------------------------------------------------------------------------------- /packages/nestjs-signed-url/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module.js' 2 | export * from './services/index.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-signed-url/src/module.ts: -------------------------------------------------------------------------------- 1 | import type { DynamicModule } from '@nestjs/common' 2 | 3 | import { Module } from '@nestjs/common' 4 | 5 | import { SignedUrlService } from './services/index.js' 6 | import { GcsStorage } from './storage/index.js' 7 | import { STORAGE } from './storage/index.js' 8 | 9 | @Module({}) 10 | export class SignedUrlModule { 11 | static gcs(): DynamicModule { 12 | const storageProvider = { 13 | provide: STORAGE, 14 | useFactory: (): GcsStorage => new GcsStorage(), 15 | } 16 | 17 | return { 18 | module: SignedUrlModule, 19 | providers: [SignedUrlService, storageProvider], 20 | exports: [SignedUrlService], 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/nestjs-signed-url/src/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './signed-url.service.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-signed-url/src/services/signed-url.service.ts: -------------------------------------------------------------------------------- 1 | import type { SignUrlOptions } from '../storage/index.js' 2 | import type { SignedUrl } from '../storage/index.js' 3 | import type { AbstractStorage } from '../storage/index.js' 4 | 5 | import { Inject } from '@nestjs/common' 6 | import { Injectable } from '@nestjs/common' 7 | 8 | import { STORAGE } from '../storage/index.js' 9 | 10 | @Injectable() 11 | export class SignedUrlService { 12 | @Inject(STORAGE) 13 | storage: AbstractStorage 14 | 15 | async generateWriteUrl( 16 | bucket: string, 17 | filename: string, 18 | options: SignUrlOptions 19 | ): Promise { 20 | return this.storage.generateWriteUrl(bucket, filename, options) 21 | } 22 | 23 | async generateReadUrl(bucket: string, filename: string): Promise { 24 | return this.storage.generateReadUrl(bucket, filename) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/nestjs-signed-url/src/storage/abstract.storage.ts: -------------------------------------------------------------------------------- 1 | import type { SignUrlOptions } from './storage.interfaces.js' 2 | import type { SignedUrl } from './storage.interfaces.js' 3 | 4 | export abstract class AbstractStorage { 5 | abstract generateWriteUrl( 6 | bucket: string, 7 | filename: string, 8 | options: SignUrlOptions 9 | ): Promise 10 | 11 | abstract generateReadUrl(bucket: string, filename: string): Promise 12 | } 13 | -------------------------------------------------------------------------------- /packages/nestjs-signed-url/src/storage/constants.ts: -------------------------------------------------------------------------------- 1 | export const STORAGE = Symbol('SIGNED_URL_UPLOAD_STORAGE_PROVIDER') 2 | -------------------------------------------------------------------------------- /packages/nestjs-signed-url/src/storage/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './storage.interfaces.js' 2 | export * from './abstract.storage.js' 3 | export * from './gcs.storage.js' 4 | export * from './constants.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-signed-url/src/storage/storage.interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface SignedUrlField { 2 | key: string 3 | value: string 4 | } 5 | 6 | export interface SignedUrl { 7 | url: string 8 | fields?: Array 9 | } 10 | 11 | export interface SignUrlOptions { 12 | type: string 13 | } 14 | -------------------------------------------------------------------------------- /packages/nestjs-typeorm-seeding/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@atls/typeorm-seeding' 2 | export * from './module/index.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-typeorm-seeding/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export * from './typeorm-seeding.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-typeorm-seeding/src/module/typeorm-seeding.module.test.ts: -------------------------------------------------------------------------------- 1 | import type { TestingModule } from '@nestjs/testing' 2 | 3 | import { SeederFactory } from '@atls/typeorm-seeding' 4 | import { Test } from '@nestjs/testing' 5 | import { TypeOrmModule } from '@nestjs/typeorm' 6 | import { describe } from '@jest/globals' 7 | import { afterEach } from '@jest/globals' 8 | import { it } from '@jest/globals' 9 | import { expect } from '@jest/globals' 10 | 11 | import { TypeOrmSeedingModule } from './typeorm-seeding.module.js' 12 | 13 | describe('typeorm-seeding', () => { 14 | describe('module', () => { 15 | let testingModule: TestingModule 16 | 17 | afterEach(async () => { 18 | await testingModule.close() 19 | }) 20 | 21 | it(`register`, async () => { 22 | testingModule = await Test.createTestingModule({ 23 | imports: [ 24 | TypeOrmSeedingModule.register(), 25 | TypeOrmModule.forRoot({ 26 | type: 'sqljs', 27 | }), 28 | ], 29 | }).compile() 30 | 31 | expect(testingModule.get(SeederFactory)).toBeDefined() 32 | }) 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /packages/nestjs-typeorm-seeding/src/module/typeorm-seeding.module.ts: -------------------------------------------------------------------------------- 1 | import type { DynamicModule } from '@nestjs/common' 2 | 3 | import { SeederFactory } from '@atls/typeorm-seeding' 4 | import { Module } from '@nestjs/common' 5 | import { DataSource } from 'typeorm' 6 | 7 | @Module({}) 8 | export class TypeOrmSeedingModule { 9 | static register(): DynamicModule { 10 | const seederFactoryProvider = { 11 | provide: SeederFactory, 12 | useFactory: (connection: DataSource) => new SeederFactory({ connection }), 13 | inject: [DataSource], 14 | } 15 | 16 | return { 17 | global: true, 18 | module: TypeOrmSeedingModule, 19 | providers: [seederFactoryProvider], 20 | exports: [seederFactoryProvider], 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/nestjs-typesense-typeorm/integration/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './typesense-typeorm-integration.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-typesense-typeorm/integration/src/test.entity.ts: -------------------------------------------------------------------------------- 1 | import { PrimaryGeneratedColumn } from 'typeorm' 2 | import { Entity } from 'typeorm' 3 | import { Column } from 'typeorm' 4 | 5 | import { Schema } from '@atls/nestjs-typesense' 6 | import { Field } from '@atls/nestjs-typesense' 7 | 8 | @Entity() 9 | @Schema({ name: 'test' }) 10 | export class TestEntity { 11 | @Field('string') 12 | @PrimaryGeneratedColumn() 13 | id!: number 14 | 15 | @Column() 16 | @Field('string') 17 | company!: string 18 | 19 | @Column() 20 | @Field('int32') 21 | employees!: number 22 | } 23 | -------------------------------------------------------------------------------- /packages/nestjs-typesense-typeorm/integration/src/typesense-typeorm-integration.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | import { TypeOrmModule } from '@nestjs/typeorm' 3 | 4 | import { TypesenseModule } from '@atls/nestjs-typesense' 5 | 6 | import { TypesenseTypeOrmModule } from '../../src/index.js' 7 | import { TestEntity } from './test.entity.js' 8 | 9 | @Module({ 10 | imports: [ 11 | TypeOrmModule.forRoot({ 12 | type: 'sqlite', 13 | database: ':memory:', 14 | entities: [TestEntity], 15 | synchronize: true, 16 | }), 17 | TypeOrmModule.forFeature([TestEntity]), 18 | TypesenseModule.register(), 19 | TypesenseTypeOrmModule.register(), 20 | ], 21 | providers: [TestEntity], 22 | exports: [TypeOrmModule], 23 | }) 24 | export class TypesenseTypeOrmIntegrationModule {} 25 | -------------------------------------------------------------------------------- /packages/nestjs-typesense-typeorm/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './module/index.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-typesense-typeorm/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './typesense-typeorm-module.interface.js' 2 | export * from './typesense-typeorm.constants.js' 3 | export * from './typesense-typeorm.module.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-typesense-typeorm/src/module/typesense-typeorm-module.interface.ts: -------------------------------------------------------------------------------- 1 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 2 | import type { Type } from '@nestjs/common/interfaces' 3 | 4 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 5 | export interface TypesenseTypeOrmModuleOptions {} 6 | 7 | export interface TypesenseTypeOrmOptionsFactory { 8 | // eslint-disable-next-line @typescript-eslint/method-signature-style 9 | createTypesenseTypeOrmOptions(): 10 | | Promise 11 | | TypesenseTypeOrmModuleOptions 12 | } 13 | 14 | export interface TypesenseTypeOrmModuleAsyncOptions extends Pick { 15 | useExisting?: Type 16 | useClass?: Type 17 | useFactory?: ( 18 | ...args: Array 19 | ) => Promise | TypesenseTypeOrmModuleOptions 20 | inject?: Array 21 | } 22 | -------------------------------------------------------------------------------- /packages/nestjs-typesense-typeorm/src/module/typesense-typeorm.constants.ts: -------------------------------------------------------------------------------- 1 | export const TYPESENSE_TYPEORM_MODULE_OPTIONS = `TYPESENSE_TYPEORM_MODULE_OPTIONS` 2 | -------------------------------------------------------------------------------- /packages/nestjs-typesense-typeorm/src/module/typesense-typeorm.providers.ts: -------------------------------------------------------------------------------- 1 | import type { Provider } from '@nestjs/common' 2 | 3 | import type { TypesenseTypeOrmModuleOptions } from './typesense-typeorm-module.interface.js' 4 | 5 | import { TypeOrmListenersBuilder } from '../typeorm/index.js' 6 | import { EntityToDocumentMapper } from '../typesense/index.js' 7 | import { TYPESENSE_TYPEORM_MODULE_OPTIONS } from './typesense-typeorm.constants.js' 8 | 9 | export const createTypesenseTypeOrmOptionsProvider = ( 10 | options: TypesenseTypeOrmModuleOptions = {} 11 | ): Array => [ 12 | { 13 | provide: TYPESENSE_TYPEORM_MODULE_OPTIONS, 14 | useValue: options, 15 | }, 16 | ] 17 | 18 | export const createTypesenseTypeOrmProvider = (): Array => [ 19 | TypeOrmListenersBuilder, 20 | EntityToDocumentMapper, 21 | ] 22 | 23 | export const createTypesenseTypeOrmExportsProvider = (): Array => [] 24 | -------------------------------------------------------------------------------- /packages/nestjs-typesense-typeorm/src/typeorm/index.ts: -------------------------------------------------------------------------------- 1 | export * from './typeorm-listeners.builder.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-typesense-typeorm/src/typesense/index.ts: -------------------------------------------------------------------------------- 1 | export * from './entity-to-document.mapper.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-typesense/src/collections/index.ts: -------------------------------------------------------------------------------- 1 | export * from './typesense-colletctions.creator.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-typesense/src/decorators/field.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common' 2 | import { applyDecorators } from '@nestjs/common' 3 | 4 | export interface FieldMetadata { 5 | name?: string 6 | facet?: boolean 7 | index?: boolean 8 | optional?: boolean 9 | } 10 | 11 | export type FieldType = 12 | | 'auto' 13 | | 'bool' 14 | | 'bool[]' 15 | | 'float' 16 | | 'float[]' 17 | | 'geopoint' 18 | | 'int32' 19 | | 'int32[]' 20 | | 'int64' 21 | | 'int64[]' 22 | | 'string' 23 | | 'string[]' 24 | 25 | export const FIELD_METADATA = '__fieldMetadata__' 26 | 27 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type 28 | export const Field = (type: FieldType, options: FieldMetadata = {}) => 29 | applyDecorators((target: object, key: string | symbol, descriptor: PropertyDescriptor) => { 30 | const exists = Reflect.getMetadata(FIELD_METADATA, target.constructor) || [] 31 | 32 | return SetMetadata(FIELD_METADATA, [ 33 | ...exists, 34 | { 35 | ...options, 36 | type, 37 | name: options.name || key, 38 | }, 39 | ])(target.constructor, key, descriptor) 40 | }) 41 | -------------------------------------------------------------------------------- /packages/nestjs-typesense/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './schema.decorator.js' 2 | export * from './field.decorator.js' 3 | -------------------------------------------------------------------------------- /packages/nestjs-typesense/src/decorators/schema.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common' 2 | import { applyDecorators } from '@nestjs/common' 3 | import decamelize from 'decamelize' 4 | 5 | export interface SchemaMetadata { 6 | name?: string 7 | defaultSortingField?: string 8 | auto?: boolean 9 | } 10 | 11 | export const SCHEMA_METADATA = '__schemaMetadata__' 12 | 13 | export const Schema = (options: SchemaMetadata = {}): ClassDecorator => 14 | applyDecorators((target: object, key: string | symbol, descriptor: PropertyDescriptor) => 15 | SetMetadata(SCHEMA_METADATA, { 16 | name: 17 | options.name || 18 | // eslint-disable-next-line @typescript-eslint/no-unsafe-argument 19 | decamelize((target as any).name, { separator: '-', preserveConsecutiveUppercase: false }), 20 | defaultSortingField: options.defaultSortingField, 21 | })(target, key, descriptor)) 22 | -------------------------------------------------------------------------------- /packages/nestjs-typesense/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './collections/index.js' 2 | export * from './metadata/index.js' 3 | export * from './decorators/index.js' 4 | export * from './module/index.js' 5 | -------------------------------------------------------------------------------- /packages/nestjs-typesense/src/metadata/index.ts: -------------------------------------------------------------------------------- 1 | export * from './typesense.metadata-accessor.js' 2 | export * from './typesense.metadata-explorer.js' 3 | export * from './typesense.metadata-registry.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-typesense/src/metadata/schema.metadata.ts: -------------------------------------------------------------------------------- 1 | import type { CollectionFieldSchema } from 'typesense/lib/Typesense/Collection.js' 2 | 3 | export interface Schema { 4 | name: string 5 | defaultSortingField: string 6 | fields: Array 7 | } 8 | -------------------------------------------------------------------------------- /packages/nestjs-typesense/src/metadata/typesense.metadata-registry.ts: -------------------------------------------------------------------------------- 1 | import type { Schema } from './schema.metadata.js' 2 | 3 | import { Logger } from '@atls/logger' 4 | import { Injectable } from '@nestjs/common' 5 | 6 | type Constructor = new (...args: Array) => object 7 | 8 | @Injectable() 9 | export class TypesenseMetadataRegistry { 10 | private logger = new Logger(TypesenseMetadataRegistry.name) 11 | 12 | private schemas: Map = new Map() 13 | 14 | addSchema(target: Constructor, schema: Schema): void { 15 | if (this.schemas.has(target)) { 16 | this.logger.warn(`Schema ${target.toString()} already exists`) 17 | } 18 | 19 | this.schemas.set(target, schema) 20 | } 21 | 22 | getSchemaByTarget(target: Constructor): Schema | undefined { 23 | return this.schemas.get(target) 24 | } 25 | 26 | getTargets(): IterableIterator { 27 | return this.schemas.keys() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/nestjs-typesense/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './typesense-module.interface.js' 2 | export * from './typesense.constants.js' 3 | export * from './typesense.module.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-typesense/src/module/typesense-module.interface.ts: -------------------------------------------------------------------------------- 1 | import type { ModuleMetadata } from '@nestjs/common/interfaces' 2 | import type { Type } from '@nestjs/common/interfaces' 3 | import type { LogLevelDesc } from 'loglevel' 4 | 5 | export interface TypesenseNodeOptions { 6 | host: string 7 | port: number 8 | protocol: string 9 | } 10 | 11 | export interface TypesenseModuleOptions { 12 | nodes?: Array 13 | numRetries?: number 14 | apiKey?: string 15 | connectionTimeoutSeconds?: number 16 | retryIntervalSeconds?: number 17 | healthcheckIntervalSeconds?: number 18 | logLevel?: LogLevelDesc 19 | } 20 | 21 | export interface TypesenseOptionsFactory { 22 | // eslint-disable-next-line @typescript-eslint/method-signature-style 23 | createTypesenseOptions(): Promise | TypesenseModuleOptions 24 | } 25 | 26 | export interface TypesenseModuleAsyncOptions extends Pick { 27 | useExisting?: Type 28 | useClass?: Type 29 | useFactory?: (...args: Array) => Promise | TypesenseModuleOptions 30 | inject?: Array 31 | } 32 | -------------------------------------------------------------------------------- /packages/nestjs-typesense/src/module/typesense.constants.ts: -------------------------------------------------------------------------------- 1 | export const TYPESENSE_MODULE_OPTIONS = 'TYPESENSE_MODULE_OPTIONS' 2 | -------------------------------------------------------------------------------- /packages/nestjs-validation/src/errors/index.ts: -------------------------------------------------------------------------------- 1 | export * from './validation.error.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-validation/src/errors/validation.error.ts: -------------------------------------------------------------------------------- 1 | import type { ValidationError as VError } from 'class-validator' 2 | 3 | export class ValidationError extends Error { 4 | constructor(public readonly errors: Array) { 5 | super() 6 | 7 | this.message = 'Validation failed' 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/nestjs-validation/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './validator/index.js' 2 | export * from './module/index.js' 3 | export * from './errors/index.js' 4 | -------------------------------------------------------------------------------- /packages/nestjs-validation/src/module/index.ts: -------------------------------------------------------------------------------- 1 | export * from './validation.module.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-validation/src/module/validation.module.ts: -------------------------------------------------------------------------------- 1 | import type { DynamicModule } from '@nestjs/common' 2 | 3 | import { Module } from '@nestjs/common' 4 | 5 | import { Validator } from '../validator/index.js' 6 | 7 | @Module({}) 8 | export class ValidationModule { 9 | static register(): DynamicModule { 10 | return { 11 | module: ValidationModule, 12 | providers: [ 13 | { 14 | provide: Validator, 15 | useClass: Validator, 16 | }, 17 | ], 18 | exports: [ 19 | { 20 | provide: Validator, 21 | useClass: Validator, 22 | }, 23 | ], 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/nestjs-validation/src/validator/index.ts: -------------------------------------------------------------------------------- 1 | export * from './validator.js' 2 | -------------------------------------------------------------------------------- /packages/nestjs-validation/src/validator/validator.ts: -------------------------------------------------------------------------------- 1 | import type { ClassConstructor } from 'class-transformer' 2 | 3 | import { plainToInstance } from 'class-transformer' 4 | import { validate } from 'class-validator' 5 | 6 | import { ValidationError } from '../errors/index.js' 7 | 8 | export class Validator { 9 | async transform(metatype: ClassConstructor, value: object): Promise { 10 | return plainToInstance(metatype, value) as T 11 | } 12 | 13 | async validate(valueOrObject: object, metatype?: ClassConstructor): Promise { 14 | const transformed = metatype ? await this.transform(metatype, valueOrObject) : valueOrObject 15 | 16 | const errors = await validate(transformed as object) 17 | 18 | if (errors.length > 0) { 19 | throw new ValidationError(errors) 20 | } 21 | 22 | return transformed as T 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /project.types.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "declaration": false, 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "esModuleInterop": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "importHelpers": false, 10 | "isolatedModules": false, 11 | "moduleResolution": "NodeNext", 12 | "noFallthroughCasesInSwitch": true, 13 | "noImplicitAny": true, 14 | "noImplicitReturns": true, 15 | "noImplicitThis": true, 16 | "noUnusedLocals": false, 17 | "noUnusedParameters": false, 18 | "pretty": true, 19 | "removeComments": true, 20 | "resolveJsonModule": true, 21 | "strict": true, 22 | "strictPropertyInitialization": false, 23 | "sourceMap": false, 24 | "module": "NodeNext", 25 | "target": "es2022", 26 | "jsx": "react", 27 | "outDir": "./dist", 28 | "noImplicitOverride": true, 29 | "skipLibCheck": true, 30 | "allowJs": true 31 | }, 32 | "include": ["project.types.d.ts", "packages/**/*", "examples/**/*"] 33 | } 34 | --------------------------------------------------------------------------------