├── .editorconfig ├── .github ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ ├── documentation.yml │ └── feature-request.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── ci.yml │ ├── generate-readme.yml │ └── lint.yml ├── .gitignore ├── .markdownlint.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── README.md.tmpl ├── examples.json ├── examples ├── cli-base │ ├── .gitignore │ ├── .pre-commit-config.yaml │ ├── README.md │ ├── VERSION.txt │ ├── install │ ├── requirements.txt │ ├── setup.py │ ├── src │ │ └── app.py │ └── uninstall ├── cli-typer-base │ ├── .gitignore │ ├── .pre-commit-config.yaml │ ├── README.md │ ├── entities │ │ ├── __init__.py │ │ └── currencies.py │ ├── main.py │ ├── requirements.txt │ ├── services │ │ ├── __init__.py │ │ ├── api_consumer.py │ │ ├── calculator.py │ │ └── input_wrapper.py │ └── tables │ │ ├── __init__.py │ │ └── exchange.py ├── fastapi-base │ ├── .gitignore │ ├── .pre-commit-config.yaml │ ├── LICENSE │ ├── README.md │ ├── requirements.txt │ ├── requiremets.dev.txt │ ├── setup.cfg │ └── src │ │ ├── __init__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── users_controller.py │ │ ├── core │ │ ├── __init__.py │ │ └── config.py │ │ ├── exceptions │ │ └── __init__.py │ │ ├── factories │ │ ├── __init__.py │ │ └── user_factory.py │ │ ├── main.py │ │ ├── models │ │ ├── __init__.py │ │ └── user_model.py │ │ ├── repository │ │ └── __init__.py │ │ ├── routes │ │ ├── __init__.py │ │ └── routers.py │ │ └── services │ │ ├── __init__.py │ │ └── user_service.py ├── fastapi-crud │ ├── .gitignore │ ├── .pre-commit-config.yaml │ ├── Dockerfile │ ├── README.md │ ├── compose.yml │ ├── requirements.dev.txt │ ├── requirements.txt │ ├── setup.cfg │ └── src │ │ ├── alembic.ini │ │ ├── alembic_migrations │ │ ├── README │ │ ├── env.py │ │ ├── script.py.mako │ │ └── versions │ │ │ ├── 11bd0063b0af_specified_not_nullable_fields_in_.py │ │ │ ├── 15509efef468_first_revision.py │ │ │ └── df8afbc693b9_add_company_model.py │ │ ├── auth │ │ └── __init__.py │ │ ├── controllers │ │ ├── __init__.py │ │ ├── company_controllers.py │ │ └── employee_controllers.py │ │ ├── core │ │ ├── __init__.py │ │ └── config.py │ │ ├── db │ │ ├── __init__.py │ │ └── database.py │ │ ├── exceptions │ │ ├── __init__.py │ │ └── database_exceptions.py │ │ ├── factories │ │ ├── __init__.py │ │ ├── companies_factory.py │ │ └── employee_factory.py │ │ ├── logging.conf │ │ ├── main.py │ │ ├── models │ │ ├── __init__.py │ │ ├── models.py │ │ └── schemas │ │ │ ├── __init__.py │ │ │ ├── company.py │ │ │ └── employee.py │ │ ├── repositories │ │ ├── __init__.py │ │ ├── company_repository.py │ │ └── employee_repository.py │ │ ├── routes │ │ ├── __init__.py │ │ ├── auth.py │ │ └── routers.py │ │ ├── scripts │ │ └── startup.sh │ │ └── services │ │ ├── __init__.py │ │ ├── company_service.py │ │ └── employee_service.py ├── fastapi-gql │ ├── .gitignore │ ├── .pre-commit-config.yaml │ ├── README.md │ ├── requirements.dev.txt │ ├── requirements.txt │ └── src │ │ ├── __init__.py │ │ ├── factories │ │ ├── __init__.py │ │ └── company_factory.py │ │ ├── main.py │ │ ├── models │ │ ├── company_model.py │ │ ├── queries.py │ │ └── types.py │ │ └── services │ │ ├── __init__.py │ │ └── company_service.py ├── fastapi-mongo-with-docker-compose │ ├── .editorconfig │ ├── .env.example │ ├── .flake8 │ ├── .github │ │ ├── ISSUE_TEMPLATE │ │ │ ├── bug-report.yml │ │ │ ├── config.yml │ │ │ ├── documentation.yml │ │ │ └── feature-request.yml │ │ ├── PULL_REQUEST_TEMPLATE.md │ │ ├── dependabot.yml │ │ └── workflows │ │ │ ├── super-lint.yml │ │ │ └── todo.yml │ ├── .gitignore │ ├── .markdownlint.json │ ├── .pre-commit-config.yaml │ ├── Dockerfile │ ├── README.md │ ├── __init__.py │ ├── app │ │ ├── __init__.py │ │ ├── config.py │ │ ├── main.py │ │ └── router │ │ │ ├── __init__.py │ │ │ └── routes.py │ ├── compose.prod.yml │ ├── compose.yml │ ├── config.py │ ├── main.py │ ├── mongo │ │ └── initdb.d │ │ │ └── mongo-init.sh │ ├── requirements.dev.txt │ ├── requirements.txt │ └── routes.py ├── fastapi-postgres-with-serverless │ ├── .env.local │ ├── .flake8 │ ├── .github │ │ ├── CODEOWNERS │ │ ├── CODE_OF_CONDUCT.md │ │ ├── ISSUE_TEMPLATE │ │ │ ├── bug-report.yml │ │ │ ├── config.yml │ │ │ ├── documentation.yml │ │ │ └── feature-request.yml │ │ ├── PULL_REQUEST_TEMPLATE.md │ │ ├── dependabot.yml │ │ └── workflows │ │ │ ├── markdownlint.yml │ │ │ ├── python-lint.yml │ │ │ ├── shellcheck.yml │ │ │ └── todo.yml │ ├── .gitignore │ ├── .markdownlint.json │ ├── .node-version │ ├── .pre-commit-config.yaml │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── postgres │ │ ├── .gitignore │ │ ├── README.md │ │ ├── compose.yml │ │ ├── initdb.d │ │ │ └── .gitkeep │ │ └── pgadmin-bootstrap │ │ │ └── server.json │ ├── requirements.dev.txt │ ├── requirements.txt │ ├── serverless.yml │ └── src │ │ ├── __init__.py │ │ ├── main.py │ │ └── router │ │ ├── __init__.py │ │ └── routes.py ├── fastapi-simple-docker-pip │ ├── .dockerignore │ ├── .env.example │ ├── .flake8 │ ├── .github │ │ ├── CODEOWNERS │ │ ├── CODE_OF_CONDUCT.md │ │ ├── ISSUE_TEMPLATE │ │ │ ├── bug-report.yml │ │ │ ├── config.yml │ │ │ ├── documentation.yml │ │ │ └── feature-request.yml │ │ ├── PULL_REQUEST_TEMPLATE.md │ │ ├── dependabot.yml │ │ └── workflows │ │ │ ├── lint.yml │ │ │ ├── security-scan.yml │ │ │ └── todo.yml │ ├── .gitignore │ ├── .markdownlint.json │ ├── .pre-commit-config.yaml │ ├── .shellcheckrc │ ├── Dockerfile │ ├── Pipfile │ ├── README.md │ ├── app │ │ ├── __init__.py │ │ ├── auth │ │ │ ├── __init__.py │ │ │ ├── auth.py │ │ │ ├── generic_auth_provider.py │ │ │ └── mock_auth_provider.py │ │ ├── config.py │ │ ├── constants.py │ │ ├── database.py │ │ ├── main.py │ │ ├── repositories │ │ │ ├── __init__.py │ │ │ └── note_repository.py │ │ ├── router │ │ │ ├── __init__.py │ │ │ ├── base_routes.py │ │ │ └── note_routes.py │ │ ├── schemas │ │ │ ├── __init__.py │ │ │ └── note.py │ │ ├── services │ │ │ ├── __init__.py │ │ │ └── email_service.py │ │ ├── types.py │ │ └── utils.py │ ├── compose.prod.yml │ ├── compose.yml │ ├── docs │ │ └── .gitkeep │ ├── pyproject.toml │ ├── scripts │ │ ├── ctl │ │ └── easy-options │ │ │ ├── easyoptions.sh │ │ │ └── example.sh │ └── tests │ │ ├── __init__.py │ │ ├── integration │ │ ├── __init__.py │ │ └── test_main_routes.py │ │ └── unit │ │ ├── __init__.py │ │ └── test_build.py ├── golang-api-with-postgres-and-sqlc │ ├── .gitignore │ ├── .sqlfluff │ ├── Dockerfile │ ├── README.md │ ├── compose.yml │ ├── db │ │ ├── database.go │ │ ├── migrations │ │ │ └── schema.sql │ │ ├── query │ │ │ └── user.sql │ │ └── sqlc │ │ │ ├── db.go │ │ │ ├── models.go │ │ │ ├── querier.go │ │ │ └── user.sql.go │ ├── go.mod │ ├── go.sum │ ├── handler │ │ └── handler.go │ ├── main.go │ ├── model │ │ └── model.go │ ├── repository │ │ └── repository.go │ ├── service │ │ └── service.go │ └── sqlc.yaml ├── golang-todo-rest-crud │ ├── .gitignore │ ├── .pre-commit-config.yaml │ ├── Makefile │ ├── README.md │ ├── cmd │ │ └── todo │ │ │ └── main.go │ ├── docker-compose.yml │ ├── docker │ │ ├── mongo │ │ │ └── initdb.d │ │ │ │ └── mongo-init.js │ │ └── todo │ │ │ └── Dockerfile │ ├── docs │ │ └── swagger.yaml │ ├── go.mod │ ├── go.sum │ ├── internal │ │ ├── config │ │ │ └── config.go │ │ ├── platform │ │ │ └── mongo │ │ │ │ ├── mongo.go │ │ │ │ ├── mongo_client_helper_mock.go │ │ │ │ ├── mongo_collection_helper_mock.go │ │ │ │ ├── mongo_cursor_helper_mock.go │ │ │ │ ├── mongo_database_helper_mock.go │ │ │ │ ├── mongo_registry.go │ │ │ │ ├── mongo_update_result_helper_mock.go │ │ │ │ └── single_result_helper_mock.go │ │ ├── ratelimit │ │ │ └── ratelimit.go │ │ ├── todo │ │ │ ├── logging.go │ │ │ ├── note │ │ │ │ ├── contract.go │ │ │ │ ├── doc.go │ │ │ │ ├── handler.go │ │ │ │ ├── handler_test.go │ │ │ │ ├── note.go │ │ │ │ ├── repository.go │ │ │ │ ├── repository_mock.go │ │ │ │ ├── repository_test.go │ │ │ │ ├── service.go │ │ │ │ ├── service_mock.go │ │ │ │ ├── service_test.go │ │ │ │ └── validator.go │ │ │ └── todo.go │ │ └── trace │ │ │ └── trace.go │ ├── pkg │ │ ├── apierror │ │ │ └── apierror.go │ │ ├── encode │ │ │ └── encode.go │ │ ├── health │ │ │ ├── health.go │ │ │ └── health_test.go │ │ └── logs │ │ │ └── logs.go │ ├── test │ │ └── integration │ │ │ ├── integration_test.go │ │ │ └── note_test.go │ └── third_party │ │ └── swagger-ui-4.11.1 │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── index.css │ │ ├── index.html │ │ ├── oauth2-redirect.html │ │ ├── swagger-initializer.js │ │ ├── swagger-ui-bundle.js │ │ ├── swagger-ui-bundle.js.map │ │ ├── swagger-ui-es-bundle-core.js │ │ ├── swagger-ui-es-bundle-core.js.map │ │ ├── swagger-ui-es-bundle.js │ │ ├── swagger-ui-es-bundle.js.map │ │ ├── swagger-ui-standalone-preset.js │ │ ├── swagger-ui-standalone-preset.js.map │ │ ├── swagger-ui.css │ │ ├── swagger-ui.css.map │ │ ├── swagger-ui.js │ │ ├── swagger-ui.js.map │ │ └── swagger.json ├── langgraph-sls-fastapi-rag │ ├── .dockerignore │ ├── .env.example │ ├── .flake8 │ ├── .gitignore │ ├── .markdownlint.json │ ├── .node-version │ ├── .pre-commit-config.yaml │ ├── .shellcheckrc │ ├── .yaml-lint.yml │ ├── Dockerfile │ ├── Pipfile │ ├── Pipfile.lock │ ├── README.md │ ├── TODO.md │ ├── app │ │ ├── __init__.py │ │ ├── config.py │ │ ├── constants.py │ │ ├── handlers │ │ │ ├── __init__.py │ │ │ └── base_handler.py │ │ ├── index_graph │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── graph.py │ │ │ ├── nodes.py │ │ │ ├── retrieval.py │ │ │ ├── router.py │ │ │ ├── services.py │ │ │ └── state.py │ │ ├── main.py │ │ ├── rag_graph │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── graph.py │ │ │ ├── nodes.py │ │ │ ├── prompts.py │ │ │ ├── retrieval.py │ │ │ ├── router.py │ │ │ ├── state.py │ │ │ └── tools.py │ │ ├── router │ │ │ ├── __init__.py │ │ │ ├── base_routes.py │ │ │ └── schemas.py │ │ ├── secrets.py │ │ ├── shared │ │ │ ├── __init__.py │ │ │ └── utils.py │ │ └── types.py │ ├── compose.prod.yml │ ├── compose.yml │ ├── create-params.sh │ ├── docker │ │ └── localstack │ │ │ ├── compose.yml │ │ │ └── init.d │ │ │ └── init-s3.sh │ ├── docs │ │ ├── AUTOMATED_DEPLOYMENT.md │ │ ├── LOCALSTACK.md │ │ ├── README.md │ │ └── SLS_DEPLOYMENT.md │ ├── langgraph.json │ ├── package.json │ ├── pnpm-lock.yaml │ ├── pyproject.toml │ ├── scripts │ │ ├── ctl │ │ └── easy-options │ │ │ ├── easyoptions.sh │ │ │ └── example.sh │ ├── serverless.yml │ ├── sls │ │ ├── envs │ │ │ ├── config.dev.yml │ │ │ ├── config.prod.yml │ │ │ └── config.staging.yml │ │ └── resource │ │ │ ├── S3.yml │ │ │ ├── bedrock.yml │ │ │ └── dynamodb-checkpointer.yml │ └── tests │ │ ├── __init__.py │ │ ├── integration │ │ ├── __init__.py │ │ ├── test_index_graph.py │ │ └── test_main_routes.py │ │ └── unit │ │ ├── __init__.py │ │ ├── test_build.py │ │ └── test_tools.py ├── nest-nats-microservices │ ├── README.md │ ├── compose.yaml │ ├── images │ │ └── logo1.svg │ ├── service-a │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .prettierrc │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── nest-cli.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.controller.spec.ts │ │ │ ├── app.controller.ts │ │ │ ├── app.module.ts │ │ │ ├── app.service.ts │ │ │ ├── main.ts │ │ │ ├── resource1 │ │ │ │ ├── dto │ │ │ │ │ ├── create-resource1.dto.ts │ │ │ │ │ └── update-resource1.dto.ts │ │ │ │ ├── entities │ │ │ │ │ └── resource1.entity.ts │ │ │ │ ├── events │ │ │ │ │ └── created.event.ts │ │ │ │ ├── resource1.controller.spec.ts │ │ │ │ ├── resource1.controller.ts │ │ │ │ ├── resource1.module.ts │ │ │ │ ├── resource1.service.spec.ts │ │ │ │ └── resource1.service.ts │ │ │ └── resource2 │ │ │ │ ├── dto │ │ │ │ ├── create-resource2.dto.ts │ │ │ │ └── update-resource2.dto.ts │ │ │ │ ├── entities │ │ │ │ └── resource2.entity.ts │ │ │ │ ├── resource2.controller.spec.ts │ │ │ │ ├── resource2.controller.ts │ │ │ │ ├── resource2.module.ts │ │ │ │ ├── resource2.service.spec.ts │ │ │ │ └── resource2.service.ts │ │ ├── test │ │ │ ├── app.e2e-spec.ts │ │ │ └── jest-e2e.json │ │ ├── tsconfig.build.json │ │ ├── tsconfig.json │ │ └── yarn.lock │ ├── service-b │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .prettierrc │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── nest-cli.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.controller.spec.ts │ │ │ ├── app.controller.ts │ │ │ ├── app.module.ts │ │ │ ├── app.service.ts │ │ │ ├── incomingEvents │ │ │ │ └── Resource1Created.event.ts │ │ │ └── main.ts │ │ ├── test │ │ │ ├── app.e2e-spec.ts │ │ │ └── jest-e2e.json │ │ ├── tsconfig.build.json │ │ ├── tsconfig.json │ │ └── yarn.lock │ └── service-c │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── .prettierrc │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── nest-cli.json │ │ ├── package.json │ │ ├── src │ │ ├── app.controller.spec.ts │ │ ├── app.controller.ts │ │ ├── app.module.ts │ │ ├── app.service.ts │ │ └── main.ts │ │ ├── test │ │ ├── app.e2e-spec.ts │ │ └── jest-e2e.json │ │ ├── tsconfig.build.json │ │ ├── tsconfig.json │ │ └── yarn.lock └── stripe-integration-node-typescript │ ├── .gitignore │ ├── .node-version │ ├── README.md │ ├── jest.config.ts │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── app.ts │ ├── core │ │ └── stripe │ │ │ ├── clients │ │ │ ├── StripeClient.ts │ │ │ └── __tests__ │ │ │ │ └── StripeClient.test.ts │ │ │ ├── schemas │ │ │ ├── __tests__ │ │ │ │ └── checkoutParams.test.ts │ │ │ └── checkoutParams.schema.ts │ │ │ ├── services │ │ │ ├── StripeService.ts │ │ │ └── __tests__ │ │ │ │ └── StripeService.test.ts │ │ │ └── types │ │ │ └── StripeCheckoutParams.ts │ └── requests.http │ └── tsconfig.json └── tools └── danger ├── .gitignore ├── .node-version ├── .nvmrc ├── dangerfile.ts ├── package-lock.json └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @ulises-jeremias @di3go-martinez @edamico 2 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This code of conduct is derived from the Ruby code of conduct. This document provides community guidelines for a safe, respectful, productive, and collaborative place for any person who is willing to contribute to this community. It applies to all “collaborative space”, which is defined as community communications channels. Any violations of the code of conduct may be reported by contacting one or more of the project maintainers either directly. 4 | 5 | - Participants will be tolerant of opposing views. 6 | - Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks. 7 | - When interpreting the words and actions of others, participants should always assume good intentions. 8 | - Behaviour that the project maintainers consider to be harassment will not be tolerated. 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | blank_issues_enabled: false 3 | contact_links: 4 | - name: 💬 General Question 5 | url: https://github.com/nanlabs/backend-reference/discussions/categories/q-a 6 | about: Please ask and answer questions as a discussion thread 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.yml: -------------------------------------------------------------------------------- 1 | name: "📕 Documentation Issue" 2 | description: Report an issue in the Reference documentation or Developer Guide 3 | title: "(short issue description)" 4 | labels: [documentation] 5 | assignees: [] 6 | body: 7 | - type: textarea 8 | id: description 9 | attributes: 10 | label: Describe the issue 11 | description: A clear and concise description of the issue. 12 | validations: 13 | required: true 14 | 15 | - type: textarea 16 | id: links 17 | attributes: 18 | label: Links 19 | description: | 20 | Include links to affected documentation page(s). 21 | validations: 22 | required: true 23 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # What's this PR do? 2 | 3 | _Summary of changes in this PR or what it accomplishes._ 4 | 5 | @ulises-jeremias @matiasz8 6 | 7 | 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/golang-todo-rest-crud/third_party/swagger-ui-4.11.1/swagger-initializer.js: -------------------------------------------------------------------------------- 1 | window.onload = function() { 2 | // 3 | 4 | // the following lines will be replaced by docker/configurator, when it runs in a docker-container 5 | window.ui = SwaggerUIBundle({ 6 | url: "swagger.json", 7 | dom_id: '#swagger-ui', 8 | deepLinking: true, 9 | presets: [ 10 | SwaggerUIBundle.presets.apis, 11 | SwaggerUIStandalonePreset 12 | ], 13 | plugins: [ 14 | SwaggerUIBundle.plugins.DownloadUrl 15 | ], 16 | layout: "StandaloneLayout" 17 | }); 18 | 19 | // 20 | }; 21 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .git 3 | .github 4 | build 5 | .devcontainer 6 | .serverless 7 | .venv 8 | .vscode 9 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/.env.example: -------------------------------------------------------------------------------- 1 | # For local development only 2 | # OpenAI API key 3 | OPENAI_API_KEY= 4 | PINECONE_API_KEY= 5 | PINECONE_INDEX_NAME= 6 | TAVILY_API_KEY= 7 | 8 | # LangSmith tracing 9 | LANGCHAIN_API_KEY= 10 | LANGCHAIN_TRACING_V2= 11 | LANGCHAIN_CALLBACKS_BACKGROUND= 12 | 13 | # AWS credentials 14 | AWS_ACCESS_KEY_ID= 15 | AWS_SECRET_ACCESS_KEY= 16 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 100 3 | max-complexity = 18 4 | select = 5 | "B", # Bugbear 6 | "C", # Cyclomatic complexity 7 | "E", # PEP8 errors 8 | "F", # PyFlakes 9 | "W", # PEP8 warnings 10 | "T4", # Flake8 plugins that check typing 11 | "B9", # Bugbear 12 | #require-plugins = 13 | # "flake8-bugbear", 14 | # "flake8-black", 15 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD041": false, 3 | "MD042": false, 4 | "MD004": false, 5 | "MD013": false, 6 | "MD033": false, 7 | "MD024": false 8 | } 9 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/.node-version: -------------------------------------------------------------------------------- 1 | 22.14.0 -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # See https://pre-commit.com for more information 3 | # See https://pre-commit.com/hooks.html for more hooks 4 | repos: 5 | - repo: https://github.com/pycqa/flake8 6 | rev: 6.0.0 7 | hooks: 8 | - id: flake8 9 | additional_dependencies: [flake8-black, flake8-bugbear] 10 | args: [--config, .flake8] 11 | - repo: https://github.com/astral-sh/ruff-pre-commit 12 | rev: v0.5.1 13 | hooks: 14 | - id: ruff 15 | args: [--fix] 16 | - repo: https://github.com/pycqa/isort 17 | rev: 5.12.0 18 | hooks: 19 | - id: isort 20 | args: [--profile, black] 21 | - repo: local 22 | hooks: 23 | - id: pytest 24 | name: pytest 25 | entry: pytest 26 | language: system 27 | pass_filenames: false 28 | always_run: true 29 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/.shellcheckrc: -------------------------------------------------------------------------------- 1 | disable=SC1090 # Non-constant source 2 | disable=SC1091 # Not specified as input 3 | disable=SC2034 # Unused variables (they are used but in other scripts) 4 | disable=SC2154 # Referenced, but not assigned 5 | disable=SC1071 # Unknown shell 6 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/.yaml-lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | 4 | ignore: | 5 | **/pnpm-lock.yaml 6 | 7 | rules: 8 | line-length: 9 | max: 100 10 | ignore: | 11 | **/workflows/lint.yml 12 | **/serverless.yml 13 | **/sls/envs/*.yml 14 | braces: 15 | max-spaces-inside: -1 # Disable spaces inside braces enforcement 16 | min-spaces-inside: -1 # Disable spaces inside braces enforcement 17 | truthy: 18 | ignore: | 19 | **/workflows/*.yml 20 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/TODO.md: -------------------------------------------------------------------------------- 1 | - [ ] Fix VALIDATE_CHECKOV 2 | - [ ] Fix VALIDATE_JSCPD 3 | - [ ] Move .flake8 to pyproject.toml 4 | - [ ] postgis images needs to run: CREATE EXTENSION IF NOT EXISTS postgis; 5 | - [ ] Model unit tests 6 | - [ ] Better pattern to handle filters. 7 | - [ ] Constants in pagination 8 | - [ ] UUID and depends catch 9 | - [ ] Check if property lists can have protected 10 | - [ ] Move hardcoded strings to constants 11 | - [ ] Pydantic UUID for Filters 12 | - [ ] Validate if impersonate_sub does not exists 13 | - [ ] Repository refactor 14 | - [ ] Minor general refactor 15 | - [ ] Validate UUID across every place 16 | - [ ] Example values and default values for pagination and bodies 17 | - [ ] Edit cognito infra to add custom fields 18 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanlabs/backend-reference/7fb09d8a392afb413db4c9e5e05d5f76f1ae04d2/examples/langgraph-sls-fastapi-rag/app/__init__.py -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/config.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import Field 3 | from pydantic_settings import BaseSettings, SettingsConfigDict 4 | 5 | from .secrets import SecretsResolver 6 | 7 | secrets = SecretsResolver() 8 | 9 | 10 | class AppSettings(BaseSettings): 11 | title: str = Field(alias="APP_TITLE", default="NaNLabs LangGraph FastAPI RAG POC") 12 | version: str = Field(alias="APP_VERSION", default="0.1.2") 13 | stage: str = Field(alias="STAGE", default="local") 14 | 15 | 16 | class AWSSettings(BaseSettings): 17 | model_config = SettingsConfigDict(extra="ignore") 18 | region: str = Field(alias="AWS_REGION", default="us-east-1") 19 | s3_bucket_name: str | None = Field(alias="AWS_S3_BUCKET_NAME", default=None) 20 | s3_endpoint_url: str | None = Field(alias="AWS_S3_ENDPOINT_URL", default=None) 21 | s3_signed_url_expiration: int | None = Field(alias="AWS_S3_SIGNED_URL_EXPIRATION", default=None) 22 | 23 | class Settings(BaseSettings): 24 | app: AppSettings = AppSettings() 25 | aws: AWSSettings = AWSSettings() 26 | 27 | 28 | settings = Settings() 29 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/constants.py: -------------------------------------------------------------------------------- 1 | ASC = "asc" 2 | DESC = "desc" 3 | 4 | ALLOWED_FILE_TYPES = [ 5 | "application/pdf", 6 | "application/vnd.ms-excel", 7 | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", 8 | "text/csv", 9 | "application/msword", 10 | "application/vnd.openxmlformats-officedocument.wordprocessingml.document", 11 | ] 12 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/handlers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanlabs/backend-reference/7fb09d8a392afb413db4c9e5e05d5f76f1ae04d2/examples/langgraph-sls-fastapi-rag/app/handlers/__init__.py -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/handlers/base_handler.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | from app.schemas.context import ContextModel 4 | 5 | 6 | class BaseHandler: 7 | def __init__(self) -> None: 8 | self.next_handler: "BaseHandler" | None = None 9 | 10 | def set_next(self, handler: "BaseHandler") -> None: 11 | self.next_handler = handler 12 | 13 | async def handle(self, context: ContextModel) -> Union[ContextModel, None]: 14 | if self.next_handler: 15 | return await self.next_handler.handle(context) 16 | return context 17 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/index_graph/__init__.py: -------------------------------------------------------------------------------- 1 | from .graph import create_graph 2 | 3 | __all__ = ["create_graph"] 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/index_graph/graph.py: -------------------------------------------------------------------------------- 1 | """This "graph" simply exposes an endpoint for a user to upload docs to be indexed.""" 2 | 3 | 4 | from langgraph.graph import StateGraph 5 | 6 | from app.index_graph import configuration, nodes, state 7 | 8 | 9 | 10 | def create_graph(): 11 | """Create and return the index graph.""" 12 | # Define a new graph 13 | builder = StateGraph(state.IndexState, config_schema=configuration.IndexConfiguration) 14 | builder.add_node(nodes.fetch_s3_content) 15 | builder.add_node(nodes.index_docs) 16 | builder.add_edge("__start__", "fetch_s3_content") 17 | builder.add_edge("fetch_s3_content", "index_docs") 18 | builder.add_edge("index_docs", "__end__") 19 | # This compiles it into a graph you can invoke and deploy. 20 | graph = builder.compile() 21 | graph.name = "S3IndexGraph" 22 | return graph 23 | 24 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/main.py: -------------------------------------------------------------------------------- 1 | from time import time 2 | 3 | from fastapi import FastAPI, Request, Response 4 | from fastapi.middleware.cors import CORSMiddleware 5 | from mangum import Mangum 6 | 7 | from app.config import settings 8 | from app.router import router as api_router 9 | 10 | app = FastAPI(title=settings.app.title, version=settings.app.version) 11 | 12 | app.add_middleware( 13 | CORSMiddleware, 14 | allow_origins=["*"], 15 | allow_credentials=True, 16 | allow_methods=["*"], 17 | allow_headers=["*"], 18 | ) 19 | 20 | @app.middleware("http") 21 | async def add_time_elapsed(request: Request, call_next) -> Response: # type: ignore 22 | start_time = time() 23 | response = await call_next(request) 24 | response.headers["X-Process-Time"] = str(time() - start_time) 25 | return response 26 | 27 | 28 | app.include_router(api_router) 29 | 30 | handler = Mangum(app) 31 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/rag_graph/__init__.py: -------------------------------------------------------------------------------- 1 | from .graph import create_graph 2 | 3 | __all__ = ["create_graph"] 4 | 5 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/rag_graph/prompts.py: -------------------------------------------------------------------------------- 1 | """Default prompts.""" 2 | 3 | RESPONSE_SYSTEM_PROMPT = """You are a helpful AI assistant. Answer the user's questions based on the retrieved documents. 4 | 5 | {retrieved_docs} 6 | 7 | Consider the following web search results: 8 | {web_search_results} 9 | 10 | System time: {system_time}""" 11 | QUERY_SYSTEM_PROMPT = """Generate search queries to retrieve documents that may help answer the user's question. Previously, you made the following queries: 12 | 13 | 14 | {queries} 15 | 16 | 17 | System time: {system_time}""" 18 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/rag_graph/tools.py: -------------------------------------------------------------------------------- 1 | from langchain_community.tools.tavily_search import TavilySearchResults 2 | from langchain_core.runnables import RunnableConfig 3 | import os 4 | from typing import Optional 5 | 6 | 7 | def create_web_search_tool(config: RunnableConfig, max_results: Optional[int] = 3): 8 | """ 9 | Creates a web search tool using the Tavily Search API. 10 | 11 | Args: 12 | config: Configuration for the runnable. 13 | max_results: Maximum number of search results to return (default: 3). 14 | 15 | Returns: 16 | An instance of TavilySearchResults configured with the provided parameters. 17 | 18 | Raises: 19 | ValueError: If TAVILY_API_KEY environment variable is not set. 20 | """ 21 | api_key = os.environ.get("TAVILY_API_KEY") 22 | if not api_key: 23 | raise ValueError( 24 | "TAVILY_API_KEY environment variable is not set. " 25 | "Please set it to use the web search tool." 26 | ) 27 | 28 | web_search_tool = TavilySearchResults(api_key=api_key, k=max_results) 29 | return web_search_tool -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/router/__init__.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter 2 | 3 | from app.index_graph.router import router as index_router 4 | from app.rag_graph.router import router as rag_router 5 | 6 | from .base_routes import router as base_routes 7 | 8 | router = APIRouter() 9 | 10 | router.include_router(base_routes, prefix="", tags=["base"]) 11 | router.include_router(index_router, prefix="/index", tags=["index"]) 12 | router.include_router(rag_router, prefix="/retrieve", tags=["rag"]) 13 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/router/base_routes.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Request 2 | 3 | router = APIRouter() 4 | 5 | 6 | @router.get("/") 7 | def root() -> dict[str, str]: 8 | return {"message": "Hello World"} 9 | 10 | 11 | @router.get("/test") 12 | def test(request: Request) -> dict[str, str]: 13 | # Return only non-sensitive headers or add access control 14 | safe_headers = {k: v for k, v in request.headers.items() 15 | if k.lower() not in ('authorization', 'cookie')} 16 | return safe_headers 17 | 18 | @router.get("/healthz") 19 | def healthcheck() -> dict[str, str]: 20 | return {"status": "ok"} 21 | 22 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/shared/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanlabs/backend-reference/7fb09d8a392afb413db4c9e5e05d5f76f1ae04d2/examples/langgraph-sls-fastapi-rag/app/shared/__init__.py -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/app/types.py: -------------------------------------------------------------------------------- 1 | from uuid import UUID 2 | 3 | FiltersTypes = str | list[str] | int | float | bool | UUID | list[UUID] 4 | FiltersData = dict[str, FiltersTypes] 5 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/compose.prod.yml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | web: 4 | build: 5 | context: . 6 | dockerfile: Dockerfile 7 | target: production 8 | ports: 9 | - "80:80" 10 | volumes: 11 | - ./app:/code/app 12 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | web: 4 | build: 5 | context: . 6 | dockerfile: Dockerfile 7 | target: builder-dev 8 | ports: 9 | - "8000:8000" 10 | env_file: 11 | - ./.env.local 12 | volumes: 13 | - ./app:/code/app 14 | command: ["uvicorn", "app.main:app", "--reload", "--host", "0.0.0.0", "--port", "8000"] 15 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/docker/localstack/compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | localstack: 4 | image: localstack/localstack:2.3.2 5 | ports: 6 | - '4566:4566' 7 | - '4510-4559:4510-4559' 8 | environment: 9 | - DEBUG=${DEBUG-} 10 | - PERSISTENCE=${PERSISTENCE-} 11 | - LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR-} 12 | - LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY-} 13 | - DOCKER_HOST=unix:///var/run/docker.sock 14 | - SERVICES=dynamodb,kinesis,s3,sqs 15 | env_file: 16 | - ./.env.local 17 | volumes: 18 | - 'localstack:/var/lib/localstack' 19 | - '/var/run/docker.sock:/var/run/docker.sock' 20 | - './docker/localstack/init.d:/etc/localstack/init/ready.d' 21 | 22 | volumes: 23 | localstack: 24 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/docker/localstack/init.d/init-s3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -z "${AWS_S3_BUCKET_NAME}" ]; then 4 | echo "AWS_S3_BUCKET_NAME is not set. Exiting." 5 | exit 1 6 | fi 7 | 8 | # Create S3 bucket 9 | awslocal s3 mb s3://"${AWS_S3_BUCKET_NAME}" 10 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/docs/LOCALSTACK.md: -------------------------------------------------------------------------------- 1 | # LocalStack 2 | 3 | ## Requirements 4 | 5 | - [docker](https://www.docker.com/) 6 | 7 | ## Resources 8 | 9 | Once the docker compose is up, it will create the following resources: 10 | 11 | - [S3 Bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html) 12 | 13 | You can check the creation of the resources in the `../docker/localstack/` folder. 14 | 15 | ## Testing 16 | 17 | From outside the container you can execute the following commands to test the service each service: 18 | 19 | - **S3** 20 | 21 | ```sh 22 | $ export AWS_ACCESS_KEY_ID=dummy-value 23 | $ export AWS_SECRET_ACCESS_KEY=dummy-value 24 | $ aws --endpoint-url=http://localhost:4566 s3 ls 25 | 2022-08-08 03:16:01 example-bucket 26 | ``` 27 | 28 | ## LocalStack Desktop 29 | 30 | You can use [LocalStack Desktop](https://docs.localstack.cloud/user-guide/tools/localstack-desktop/) to manage the resources created by the docker compose. 31 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/docs/README.md: -------------------------------------------------------------------------------- 1 | # Extra Documentation 2 | 3 | This folder contains extra documentation for the project such us project structure, configuration, etc. 4 | 5 | ## Resources 6 | 7 | - [Automated Deployment](./AUTOMATED_DEPLOYMENT.md) - Learn how our automated deployment works using GitHub Actions 8 | - [Serverless Deployment docs](./SLS_DEPLOYMENT.md) - Documentation on how to deploy the project to AWS Lambda using Serverless Framework 9 | - [LocalStack docs](./LOCALSTACK.md) - Learn how to use LocalStack for local development 10 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/docs/SLS_DEPLOYMENT.md: -------------------------------------------------------------------------------- 1 | # Serverless Deployment 2 | 3 | [![serverless](http://public.serverless.com/badges/v3.svg)](http://www.serverless.com) 4 | 5 | We use Serverless Framework to do production ready deployments. 6 | 7 | ## Requirements 8 | 9 | **You’ll need to have Node 18 or later on your local development machine** (but it’s not required on the server). You can use [fnm](https://github.com/Schniz/fnm) to easily switch Node versions between different projects. 10 | 11 | ```sh 12 | fnm use 13 | pnpm install 14 | ``` 15 | 16 | ## AWS Lambda Deployment 17 | 18 | To deploy the app to AWS, you'll first need to configure your AWS credentials. There are many ways 19 | to set your credentials, for more information refer to the [AWS documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html). 20 | 21 | Once set you can deploy your app using the serverless framework with: 22 | 23 | ```sh 24 | pnpm run sls:deploy --stage 25 | ``` 26 | 27 | for example, to deploy to the `staging` stage: 28 | 29 | ```sh 30 | pnpm run sls:deploy --stage staging 31 | ``` 32 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/langgraph.json: -------------------------------------------------------------------------------- 1 | { 2 | "dockerfile_lines": [ 3 | "RUN pip install pipenv", 4 | "COPY Pipfile Pipfile.lock ./", 5 | "RUN pipenv install --system --deploy", 6 | "RUN pip install langgraph-checkpoint-amazon-dynamodb==0.1.1" 7 | ], 8 | "graphs": { 9 | "indexer": "./app/index_graph/graph.py:create_graph", 10 | "retriever": "./app/rag_graph/graph.py:create_graph" 11 | }, 12 | "env": ".env.local", 13 | "python_version": "3.12", 14 | "dependencies": [ 15 | "." 16 | ] 17 | } -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "langgraph-sls-fastapi-rag", 3 | "version": "1.0.0", 4 | "description": "NaNLABS LangGraph FastAPI RAG POC", 5 | "main": "index.js", 6 | "scripts": { 7 | "sls": "serverless", 8 | "sls:deploy": "serverless deploy", 9 | "sls:deploy:dev": "serverless deploy --stage dev", 10 | "sls:deploy:staging": "serverless deploy --stage staging", 11 | "sls:deploy:prod": "serverless deploy --stage prod", 12 | "sls:package": "serverless package", 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+ssh://git@github.com:nanlabs/langgraph-sls-fastapi-rag.git" 18 | }, 19 | "author": "nanlabs", 20 | "homepage": "https://github.com/nanlabs/langgraph-sls-fastapi-rag#readme", 21 | "devDependencies": { 22 | "serverless": "^4.0.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=61.0"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "langgraph-sls-fastapi-rag" 7 | version = "0.1.0" 8 | description = "LangGraph API" 9 | 10 | [tool.setuptools] 11 | packages = ["app"] 12 | 13 | 14 | [tool.black] 15 | line-length = 100 16 | 17 | [tool.pylint."messages_control"] 18 | max-line-length = 100 19 | disable = [ 20 | "missing-module-docstring", 21 | "missing-class-docstring", 22 | "missing-function-docstring", 23 | "too-few-public-methods", 24 | "duplicate-code", 25 | ] 26 | ignored-modules="alembic.context" 27 | 28 | [tool.pytest.ini_options] 29 | asyncio_mode = "auto" 30 | 31 | [tool.mypy] 32 | plugins = [ 33 | "pydantic.mypy", 34 | ] 35 | 36 | follow_imports = "silent" 37 | warn_redundant_casts = true 38 | warn_unused_ignores = true 39 | disallow_any_generics = true 40 | check_untyped_defs = true 41 | no_implicit_reexport = true 42 | 43 | # for strict mypy: (this is the tricky one :-)) 44 | disallow_untyped_defs = true 45 | 46 | [tool.mypy-botocore] 47 | ignore_missing_imports = true 48 | 49 | [tool.pydantic-mypy] 50 | init_forbid_extra = true 51 | init_typed = true 52 | warn_required_dynamic_aliases = true 53 | 54 | [tool.isort] 55 | profile = "black" 56 | line_length = 100 57 | src_paths = ["app", "test"] 58 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/sls/envs/config.dev.yml: -------------------------------------------------------------------------------- 1 | --- 2 | openai_api_key: ${ssm:/${self:service}/${sls:stage}/openai-api-key} 3 | pinecone_api_key: ${ssm:/${self:service}/${sls:stage}/pinecone-api-key} 4 | pinecone_index_name: ${ssm:/${self:service}/${sls:stage}/pinecone-index-name} 5 | tavily_api_key: ${ssm:/${self:service}/${sls:stage}/tavily-api-key} 6 | 7 | langsmith_api_key: ${ssm:/${self:service}/common/langsmith-api-key} 8 | langsmith_tracing_v2: ${ssm:/${self:service}/common/langsmith-tracing-v2} 9 | langsmith_callbacks_background: ${ssm:/${self:service}/common/langsmith-callbacks-background} 10 | 11 | s3_bucket_name: ${ssm:/${self:service}/${sls:stage}/s3-bucket-name} 12 | checkpoints_table_name: ${ssm:/${self:service}/common/checkpoints-table-name} 13 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/sls/envs/config.prod.yml: -------------------------------------------------------------------------------- 1 | --- 2 | openai_api_key: ${ssm:/${self:service}/${sls:stage}/openai-api-key} 3 | pinecone_api_key: ${ssm:/${self:service}/${sls:stage}/pinecone-api-key} 4 | pinecone_index_name: ${ssm:/${self:service}/${sls:stage}/pinecone-index-name} 5 | tavily_api_key: ${ssm:/${self:service}/${sls:stage}/tavily-api-key} 6 | 7 | langsmith_api_key: ${ssm:/${self:service}/common/langsmith-api-key} 8 | langsmith_tracing_v2: ${ssm:/${self:service}/common/langsmith-tracing-v2} 9 | langsmith_callbacks_background: ${ssm:/${self:service}/common/langsmith-callbacks-background} 10 | 11 | s3_bucket_name: ${ssm:/${self:service}/${sls:stage}/s3-bucket-name} 12 | checkpoints_table_name: ${ssm:/${self:service}/common/checkpoints-table-name} -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/sls/envs/config.staging.yml: -------------------------------------------------------------------------------- 1 | --- 2 | openai_api_key: ${ssm:/${self:service}/${sls:stage}/openai-api-key} 3 | pinecone_api_key: ${ssm:/${self:service}/${sls:stage}/pinecone-api-key} 4 | pinecone_index_name: ${ssm:/${self:service}/${sls:stage}/pinecone-index-name} 5 | tavily_api_key: ${ssm:/${self:service}/${sls:stage}/tavily-api-key} 6 | 7 | langsmith_api_key: ${ssm:/${self:service}/common/langsmith-api-key} 8 | langsmith_tracing_v2: ${ssm:/${self:service}/common/langsmith-tracing-v2} 9 | langsmith_callbacks_background: ${ssm:/${self:service}/common/langsmith-callbacks-background} 10 | 11 | s3_bucket_name: ${ssm:/${self:service}/${sls:stage}/s3-bucket-name} 12 | checkpoints_table_name: ${ssm:/${self:service}/common/checkpoints-table-name} -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/sls/resource/S3.yml: -------------------------------------------------------------------------------- 1 | --- 2 | Resources: 3 | S3Bucket: 4 | Type: AWS::S3::Bucket 5 | Properties: 6 | BucketName: ${file(sls/envs/config.${sls:stage}.yml):s3_bucket_name} 7 | CorsConfiguration: 8 | CorsRules: 9 | - AllowedHeaders: 10 | - "*" 11 | AllowedMethods: 12 | - GET 13 | - PUT 14 | - HEAD 15 | - POST 16 | AllowedOrigins: 17 | - "*" 18 | PublicAccessBlockConfiguration: 19 | BlockPublicAcls: true 20 | IgnorePublicAcls: true 21 | BlockPublicPolicy: false 22 | RestrictPublicBuckets: false 23 | 24 | S3BucketPolicy: 25 | Type: AWS::S3::BucketPolicy 26 | Properties: 27 | Bucket: !Ref S3Bucket 28 | PolicyDocument: 29 | Version: "2012-10-17" 30 | Statement: 31 | - Sid: PublicReadGetObject 32 | Effect: Allow 33 | Principal: "*" 34 | Action: "s3:GetObject" 35 | Resource: "arn:aws:s3:::${file(sls/envs/config.${sls:stage}.yml):s3_bucket_name}/*" 36 | 37 | Outputs: 38 | S3BucketNameOutputKey: 39 | Value: !Ref S3Bucket 40 | Description: S3 bucket for programs 41 | Export: 42 | Name: ${self:service}-${sls:stage}-programs-s3-bucket 43 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/sls/resource/bedrock.yml: -------------------------------------------------------------------------------- 1 | Resources: 2 | BedrockIamPolicy: 3 | Type: AWS::IAM::Policy 4 | Properties: 5 | PolicyName: ${self:service}-${sls:stage}-bedrock-invoke-model-policy 6 | PolicyDocument: 7 | Version: '2012-10-17' 8 | Statement: 9 | - Effect: Allow 10 | Action: 11 | - bedrock:InvokeModel 12 | Resource: 13 | - "arn:aws:bedrock:${aws:region}::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0" 14 | - "arn:aws:bedrock:${aws:region}::foundation-model/*" 15 | Roles: 16 | - Ref: IamRoleLambdaExecution -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/sls/resource/dynamodb-checkpointer.yml: -------------------------------------------------------------------------------- 1 | Resources: 2 | DynamoDBAccessPolicy: 3 | Type: AWS::IAM::Policy 4 | Properties: 5 | PolicyName: ${self:service}-${sls:stage}-dynamodb-access 6 | PolicyDocument: 7 | Version: '2012-10-17' 8 | Statement: 9 | - Effect: Allow 10 | Action: 11 | - dynamodb:* 12 | Resource: 13 | - !GetAtt CheckpointTable.Arn 14 | 15 | Roles: 16 | - Ref: IamRoleLambdaExecution 17 | 18 | CheckpointTable: 19 | Type: AWS::DynamoDB::Table 20 | Properties: 21 | TableName: ${self:service}-${sls:stage}-checkpoint 22 | BillingMode: PAY_PER_REQUEST 23 | AttributeDefinitions: 24 | - AttributeName: PK 25 | AttributeType: S 26 | - AttributeName: SK 27 | AttributeType: S 28 | KeySchema: 29 | - AttributeName: PK 30 | KeyType: HASH 31 | - AttributeName: SK 32 | KeyType: RANGE 33 | PointInTimeRecoverySpecification: 34 | PointInTimeRecoveryEnabled: true 35 | SSESpecification: 36 | SSEEnabled: true 37 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanlabs/backend-reference/7fb09d8a392afb413db4c9e5e05d5f76f1ae04d2/examples/langgraph-sls-fastapi-rag/tests/__init__.py -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/tests/integration/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanlabs/backend-reference/7fb09d8a392afb413db4c9e5e05d5f76f1ae04d2/examples/langgraph-sls-fastapi-rag/tests/integration/__init__.py -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/tests/integration/test_main_routes.py: -------------------------------------------------------------------------------- 1 | # import pytest 2 | # from fastapi import status 3 | # from httpx import AsyncClient 4 | 5 | # from app.main import app 6 | 7 | 8 | # @pytest.fixture 9 | # async def client(): 10 | # async with AsyncClient(app=app, base_url="http://test") as ac: 11 | # yield ac 12 | 13 | 14 | # @pytest.mark.asyncio 15 | # async def test_root_endpoint(client): # pylint: disable=redefined-outer-name 16 | # response = await client.get("/") 17 | # assert response.status_code == status.HTTP_200_OK 18 | # assert response.json() == {"message": "Hello World"} 19 | 20 | 21 | # @pytest.mark.asyncio 22 | # async def test_healthcheck_endpoint(client): # pylint: disable=redefined-outer-name 23 | # response = await client.get("/healthz") 24 | # assert response.status_code == status.HTTP_200_OK 25 | # assert response.json() == {"status": "ok"} 26 | 27 | 28 | # @pytest.mark.asyncio 29 | # async def test_healthcheck_auth_endpoint_no_auth(client): # pylint: disable=redefined-outer-name 30 | # response = await client.get("/healthz-auth") 31 | # assert response.status_code == status.HTTP_403_FORBIDDEN 32 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/tests/unit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanlabs/backend-reference/7fb09d8a392afb413db4c9e5e05d5f76f1ae04d2/examples/langgraph-sls-fastapi-rag/tests/unit/__init__.py -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/tests/unit/test_build.py: -------------------------------------------------------------------------------- 1 | # from fastapi.testclient import TestClient 2 | 3 | # from app.main import app 4 | 5 | # client = TestClient(app) 6 | 7 | 8 | # def test_healthcheck(): 9 | # response = client.get("/healthz") 10 | # assert response.status_code == 200 11 | # assert response.json() == {"status": "ok"} 12 | -------------------------------------------------------------------------------- /examples/langgraph-sls-fastapi-rag/tests/unit/test_tools.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from unittest.mock import patch 3 | from langchain_core.runnables import RunnableConfig 4 | from app.rag_graph.tools import create_web_search_tool 5 | 6 | 7 | def test_create_web_search_tool_with_api_key(): 8 | """Test creating web search tool with valid API key.""" 9 | with patch.dict('os.environ', {'TAVILY_API_KEY': 'test-key'}): 10 | config = RunnableConfig() 11 | tool = create_web_search_tool(config) 12 | assert tool.api_key == 'test-key' 13 | assert tool.k == 3 # default max_results 14 | 15 | 16 | def test_create_web_search_tool_custom_max_results(): 17 | """Test creating web search tool with custom max_results.""" 18 | with patch.dict('os.environ', {'TAVILY_API_KEY': 'test-key'}): 19 | config = RunnableConfig() 20 | tool = create_web_search_tool(config, max_results=5) 21 | assert tool.k == 5 22 | 23 | 24 | def test_create_web_search_tool_missing_api_key(): 25 | """Test creating web search tool without API key raises error.""" 26 | with patch.dict('os.environ', {}, clear=True): 27 | config = RunnableConfig() 28 | with pytest.raises(ValueError) as exc_info: 29 | create_web_search_tool(config) 30 | assert "TAVILY_API_KEY environment variable is not set" in str(exc_info.value) -------------------------------------------------------------------------------- /examples/nest-nats-microservices/compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | nats: 5 | container_name: nats 6 | entrypoint: '/nats-server -c nats-server.conf -DV' 7 | image: nats 8 | ports: 9 | - '4222:4222' 10 | - '6222:6222' 11 | - '8222:8222' 12 | 13 | service-a: 14 | build: ./service-a 15 | x-develop: 16 | watch: 17 | - action: sync 18 | path: ./service-a/src 19 | target: /app/src 20 | - action: rebuild 21 | path: package.json 22 | container_name: service-a 23 | ports: 24 | - '3000:3000' 25 | 26 | service-b: 27 | build: ./service-b 28 | x-develop: 29 | watch: 30 | - action: sync 31 | path: ./service-b/src 32 | target: /app/src 33 | - action: rebuild 34 | path: package.json 35 | container_name: service-b 36 | ports: 37 | - '3001:3001' 38 | 39 | service-c: 40 | build: ./service-c 41 | x-develop: 42 | watch: 43 | - action: sync 44 | path: ./service-c/src 45 | target: /app/src 46 | - action: rebuild 47 | path: package.json 48 | container_name: service-c 49 | ports: 50 | - '3002:3002' -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | tsconfigRootDir: __dirname, 6 | sourceType: 'module', 7 | }, 8 | plugins: ['@typescript-eslint/eslint-plugin'], 9 | extends: [ 10 | 'plugin:@typescript-eslint/recommended', 11 | 'plugin:prettier/recommended', 12 | ], 13 | root: true, 14 | env: { 15 | node: true, 16 | jest: true, 17 | }, 18 | ignorePatterns: ['.eslintrc.js'], 19 | rules: { 20 | '@typescript-eslint/interface-name-prefix': 'off', 21 | '@typescript-eslint/explicit-function-return-type': 'off', 22 | '@typescript-eslint/explicit-module-boundary-types': 'off', 23 | '@typescript-eslint/no-explicit-any': 'off', 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | pnpm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # OS 15 | .DS_Store 16 | 17 | # Tests 18 | /coverage 19 | /.nyc_output 20 | 21 | # IDEs and editors 22 | /.idea 23 | .project 24 | .classpath 25 | .c9/ 26 | *.launch 27 | .settings/ 28 | *.sublime-workspace 29 | 30 | # IDE - VSCode 31 | .vscode/* 32 | !.vscode/settings.json 33 | !.vscode/tasks.json 34 | !.vscode/launch.json 35 | !.vscode/extensions.json -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18-alpine 2 | WORKDIR /app 3 | COPY . . 4 | RUN yarn 5 | CMD ["yarn", "start:dev"] 6 | EXPOSE 3000 -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/README.md: -------------------------------------------------------------------------------- 1 |

2 | Nest Logo 3 |

4 | 5 | ## Description 6 | 7 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. 8 | 9 | ## Installation 10 | 11 | ```bash 12 | yarn install 13 | ``` 14 | 15 | ## Running the app 16 | 17 | ```bash 18 | # development 19 | yarn run start 20 | 21 | # watch mode 22 | yarn run start:dev 23 | 24 | # production mode 25 | yarn run start:prod 26 | ``` 27 | 28 | ## Test 29 | 30 | ```bash 31 | # unit tests 32 | yarn run test 33 | 34 | # e2e tests 35 | yarn run test:e2e 36 | 37 | # test coverage 38 | yarn run test:cov 39 | ``` 40 | 41 | ## Support 42 | 43 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). 44 | 45 | ## Stay in touch 46 | 47 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) 48 | - Website - [https://nestjs.com](https://nestjs.com/) 49 | - Twitter - [@nestframework](https://twitter.com/nestframework) 50 | 51 | ## License 52 | 53 | Nest is [MIT licensed](LICENSE). 54 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src", 5 | "compilerOptions": { 6 | "deleteOutDir": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/app.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | 5 | describe('AppController', () => { 6 | let appController: AppController; 7 | 8 | beforeEach(async () => { 9 | const app: TestingModule = await Test.createTestingModule({ 10 | controllers: [AppController], 11 | providers: [AppService], 12 | }).compile(); 13 | 14 | appController = app.get(AppController); 15 | }); 16 | 17 | describe('root', () => { 18 | it('should return "Hello World!"', () => { 19 | expect(appController.getHello()).toBe('Hello World!'); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | import { AppService } from './app.service'; 3 | 4 | @Controller() 5 | export class AppController { 6 | constructor(private readonly appService: AppService) {} 7 | 8 | @Get('/version') 9 | getVersion(): string { 10 | return this.appService.getVersion(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | import { Resource1Module } from './resource1/resource1.module'; 5 | import { Resource2Module } from './resource2/resource2.module'; 6 | 7 | @Module({ 8 | imports: [Resource1Module, Resource2Module], 9 | controllers: [AppController], 10 | providers: [AppService], 11 | }) 12 | export class AppModule {} 13 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | getVersion(): string { 6 | return process.env.VERSION || '0.0.1'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | 4 | async function bootstrap() { 5 | const app = await NestFactory.create(AppModule); 6 | await app.listen(3000); 7 | } 8 | bootstrap(); 9 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource1/dto/create-resource1.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateResource1Dto { 2 | public id: string; 3 | public isActive: boolean; 4 | } 5 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource1/dto/update-resource1.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateResource1Dto } from './create-resource1.dto'; 3 | 4 | export class UpdateResource1Dto extends PartialType(CreateResource1Dto) {} 5 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource1/entities/resource1.entity.ts: -------------------------------------------------------------------------------- 1 | export class Resource1 {} 2 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource1/events/created.event.ts: -------------------------------------------------------------------------------- 1 | import { CreateResource1Dto } from '../dto/create-resource1.dto'; 2 | 3 | export const PATTERN = 'resource_1_created'; 4 | 5 | export class Resource1Created { 6 | public readonly pattern = PATTERN; 7 | public readonly v: number = 1; 8 | constructor(public readonly data: CreateResource1Dto) {} 9 | } 10 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource1/resource1.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { Resource1Controller } from './resource1.controller'; 3 | import { Resource1Service } from './resource1.service'; 4 | 5 | describe('Resource1Controller', () => { 6 | let controller: Resource1Controller; 7 | 8 | beforeEach(async () => { 9 | const module: TestingModule = await Test.createTestingModule({ 10 | controllers: [Resource1Controller], 11 | providers: [Resource1Service], 12 | }).compile(); 13 | 14 | controller = module.get(Resource1Controller); 15 | }); 16 | 17 | it('should be defined', () => { 18 | expect(controller).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource1/resource1.controller.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Body, 3 | Controller, 4 | Delete, 5 | Get, 6 | Param, 7 | Patch, 8 | Post, 9 | } from '@nestjs/common'; 10 | import { CreateResource1Dto } from './dto/create-resource1.dto'; 11 | import { UpdateResource1Dto } from './dto/update-resource1.dto'; 12 | import { Resource1Service } from './resource1.service'; 13 | 14 | @Controller('resource1') 15 | export class Resource1Controller { 16 | constructor(private readonly resource1Service: Resource1Service) {} 17 | 18 | @Post() 19 | create(@Body() createResource1Dto: CreateResource1Dto) { 20 | return this.resource1Service.create(createResource1Dto); 21 | } 22 | 23 | @Get() 24 | findAll() { 25 | return this.resource1Service.findAll(); 26 | } 27 | 28 | @Get(':id') 29 | findOne(@Param('id') id: string) { 30 | return this.resource1Service.findOne(id); 31 | } 32 | 33 | @Patch(':id') 34 | update( 35 | @Param('id') id: string, 36 | @Body() updateResource1Dto: UpdateResource1Dto, 37 | ) { 38 | return this.resource1Service.update(id, updateResource1Dto); 39 | } 40 | 41 | @Delete(':id') 42 | remove(@Param('id') id: string) { 43 | return this.resource1Service.remove(id); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource1/resource1.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ClientsModule, Transport } from '@nestjs/microservices'; 3 | import { Resource1Controller } from './resource1.controller'; 4 | import { Resource1Service } from './resource1.service'; 5 | 6 | @Module({ 7 | imports: [ 8 | ClientsModule.register([ 9 | { 10 | name: 'NATS', 11 | transport: Transport.NATS, 12 | options: { 13 | servers: [process.env.NATS_SERVER || 'nats://nats:4222'], 14 | }, 15 | }, 16 | ]), 17 | ], 18 | controllers: [Resource1Controller], 19 | providers: [Resource1Service], 20 | }) 21 | export class Resource1Module {} 22 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource1/resource1.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { Resource1Service } from './resource1.service'; 3 | 4 | describe('Resource1Service', () => { 5 | let service: Resource1Service; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [Resource1Service], 10 | }).compile(); 11 | 12 | service = module.get(Resource1Service); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource1/resource1.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject, Injectable } from '@nestjs/common'; 2 | import { ClientProxy } from '@nestjs/microservices'; 3 | import { v4 } from 'uuid'; 4 | import { CreateResource1Dto } from './dto/create-resource1.dto'; 5 | import { UpdateResource1Dto } from './dto/update-resource1.dto'; 6 | import { 7 | Resource1Created, 8 | PATTERN as Resource1CreatedPattern, 9 | } from './events/created.event'; 10 | 11 | @Injectable() 12 | export class Resource1Service { 13 | constructor(@Inject('NATS') private readonly natsClient: ClientProxy) {} 14 | 15 | create(createResource1Dto: CreateResource1Dto) { 16 | const id = v4(); 17 | this.natsClient.emit( 18 | Resource1CreatedPattern, 19 | new Resource1Created({ ...createResource1Dto, id }), 20 | ); 21 | return 'This action adds a new resource1'; 22 | } 23 | 24 | findAll() { 25 | return `This action returns all resource1`; 26 | } 27 | 28 | findOne(id: string) { 29 | return `This action returns a #${id} resource1`; 30 | } 31 | 32 | update(id: string, updateResource1Dto: UpdateResource1Dto) { 33 | return `This action updates a #${id} resource1`; 34 | } 35 | 36 | remove(id: string) { 37 | return `This action removes a #${id} resource1`; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource2/dto/create-resource2.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateResource2Dto {} 2 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource2/dto/update-resource2.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateResource2Dto } from './create-resource2.dto'; 3 | 4 | export class UpdateResource2Dto extends PartialType(CreateResource2Dto) {} 5 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource2/entities/resource2.entity.ts: -------------------------------------------------------------------------------- 1 | export class Resource2 {} 2 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource2/resource2.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { Resource2Controller } from './resource2.controller'; 3 | import { Resource2Service } from './resource2.service'; 4 | 5 | describe('Resource2Controller', () => { 6 | let controller: Resource2Controller; 7 | 8 | beforeEach(async () => { 9 | const module: TestingModule = await Test.createTestingModule({ 10 | controllers: [Resource2Controller], 11 | providers: [Resource2Service], 12 | }).compile(); 13 | 14 | controller = module.get(Resource2Controller); 15 | }); 16 | 17 | it('should be defined', () => { 18 | expect(controller).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource2/resource2.controller.ts: -------------------------------------------------------------------------------- 1 | import { Body, Controller, Get, Param, Post } from '@nestjs/common'; 2 | import { CreateResource2Dto } from './dto/create-resource2.dto'; 3 | import { Resource2Service } from './resource2.service'; 4 | 5 | @Controller('resource2') 6 | export class Resource2Controller { 7 | constructor(private readonly resource2Service: Resource2Service) {} 8 | 9 | @Post() 10 | create(@Body() createResource2Dto: CreateResource2Dto) { 11 | return this.resource2Service.create(createResource2Dto); 12 | } 13 | 14 | @Get() 15 | findHelloMessage() { 16 | return this.resource2Service.findHelloMessage(); 17 | } 18 | 19 | @Get(':id') 20 | findOne(@Param('id') id: string) { 21 | return this.resource2Service.findOne(id); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource2/resource2.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ClientsModule, Transport } from '@nestjs/microservices'; 3 | import { Resource2Controller } from './resource2.controller'; 4 | import { Resource2Service } from './resource2.service'; 5 | 6 | @Module({ 7 | imports: [ 8 | ClientsModule.register([ 9 | { 10 | name: 'NATS', 11 | transport: Transport.NATS, 12 | options: { 13 | servers: [process.env.NATS_SERVER || 'nats://nats:4222'], 14 | }, 15 | }, 16 | ]), 17 | ], 18 | controllers: [Resource2Controller], 19 | providers: [Resource2Service], 20 | }) 21 | export class Resource2Module {} 22 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource2/resource2.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { Resource2Service } from './resource2.service'; 3 | 4 | describe('Resource2Service', () => { 5 | let service: Resource2Service; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [Resource2Service], 10 | }).compile(); 11 | 12 | service = module.get(Resource2Service); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/src/resource2/resource2.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject, Injectable } from '@nestjs/common'; 2 | import { ClientProxy } from '@nestjs/microservices'; 3 | import { CreateResource2Dto } from './dto/create-resource2.dto'; 4 | 5 | @Injectable() 6 | export class Resource2Service { 7 | constructor(@Inject('NATS') private readonly natsClient: ClientProxy) {} 8 | 9 | create(createResource2Dto: CreateResource2Dto) { 10 | return 'This action adds a new resource2'; 11 | } 12 | 13 | findHelloMessage() { 14 | return this.natsClient.send('get_hello', {}); 15 | } 16 | 17 | findOne(id: string) { 18 | return `This action returns a #${id} resource2`; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { INestApplication } from '@nestjs/common'; 3 | import * as request from 'supertest'; 4 | import { AppModule } from './../src/app.module'; 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication; 8 | 9 | beforeEach(async () => { 10 | const moduleFixture: TestingModule = await Test.createTestingModule({ 11 | imports: [AppModule], 12 | }).compile(); 13 | 14 | app = moduleFixture.createNestApplication(); 15 | await app.init(); 16 | }); 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-a/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "ES2021", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true, 14 | "skipLibCheck": true, 15 | "strictNullChecks": false, 16 | "noImplicitAny": false, 17 | "strictBindCallApply": false, 18 | "forceConsistentCasingInFileNames": false, 19 | "noFallthroughCasesInSwitch": false 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | tsconfigRootDir: __dirname, 6 | sourceType: 'module', 7 | }, 8 | plugins: ['@typescript-eslint/eslint-plugin'], 9 | extends: [ 10 | 'plugin:@typescript-eslint/recommended', 11 | 'plugin:prettier/recommended', 12 | ], 13 | root: true, 14 | env: { 15 | node: true, 16 | jest: true, 17 | }, 18 | ignorePatterns: ['.eslintrc.js'], 19 | rules: { 20 | '@typescript-eslint/interface-name-prefix': 'off', 21 | '@typescript-eslint/explicit-function-return-type': 'off', 22 | '@typescript-eslint/explicit-module-boundary-types': 'off', 23 | '@typescript-eslint/no-explicit-any': 'off', 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | pnpm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # OS 15 | .DS_Store 16 | 17 | # Tests 18 | /coverage 19 | /.nyc_output 20 | 21 | # IDEs and editors 22 | /.idea 23 | .project 24 | .classpath 25 | .c9/ 26 | *.launch 27 | .settings/ 28 | *.sublime-workspace 29 | 30 | # IDE - VSCode 31 | .vscode/* 32 | !.vscode/settings.json 33 | !.vscode/tasks.json 34 | !.vscode/launch.json 35 | !.vscode/extensions.json -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18-alpine 2 | WORKDIR /app 3 | COPY . . 4 | RUN yarn 5 | CMD ["yarn", "start:dev"] 6 | EXPOSE 3001 -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/README.md: -------------------------------------------------------------------------------- 1 |

2 | Nest Logo 3 |

4 | 5 | ## Description 6 | 7 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. 8 | 9 | ## Installation 10 | 11 | ```bash 12 | yarn install 13 | ``` 14 | 15 | ## Running the app 16 | 17 | ```bash 18 | # development 19 | yarn run start 20 | 21 | # watch mode 22 | yarn run start:dev 23 | 24 | # production mode 25 | yarn run start:prod 26 | ``` 27 | 28 | ## Test 29 | 30 | ```bash 31 | # unit tests 32 | yarn run test 33 | 34 | # e2e tests 35 | yarn run test:e2e 36 | 37 | # test coverage 38 | yarn run test:cov 39 | ``` 40 | 41 | ## Support 42 | 43 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). 44 | 45 | ## Stay in touch 46 | 47 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) 48 | - Website - [https://nestjs.com](https://nestjs.com/) 49 | - Twitter - [@nestframework](https://twitter.com/nestframework) 50 | 51 | ## License 52 | 53 | Nest is [MIT licensed](LICENSE). 54 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src", 5 | "compilerOptions": { 6 | "deleteOutDir": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/src/app.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | 5 | describe('AppController', () => { 6 | let appController: AppController; 7 | 8 | beforeEach(async () => { 9 | const app: TestingModule = await Test.createTestingModule({ 10 | controllers: [AppController], 11 | providers: [AppService], 12 | }).compile(); 13 | 14 | appController = app.get(AppController); 15 | }); 16 | 17 | describe('root', () => { 18 | it('should return "Hello World!"', () => { 19 | expect(appController.getHello()).toBe('Hello World!'); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, UsePipes } from '@nestjs/common'; 2 | import { EventPattern } from '@nestjs/microservices'; 3 | import { AppService } from './app.service'; 4 | import { 5 | Resource1Created, 6 | PATTERN as Resource1CreatedPattern, 7 | Resource1CreatedValidationPipe, 8 | } from './incomingEvents/Resource1Created.event'; 9 | 10 | @Controller() 11 | export class AppController { 12 | constructor(private readonly appService: AppService) {} 13 | 14 | @Get() 15 | getHello(): string { 16 | return this.appService.getHello(); 17 | } 18 | 19 | @EventPattern(Resource1CreatedPattern) 20 | @UsePipes(new Resource1CreatedValidationPipe()) 21 | handleResource1Created(data: Resource1Created) { 22 | console.log('received Resource1', data); 23 | this.appService.handleResource1Created(data); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | 5 | @Module({ 6 | controllers: [AppController], 7 | providers: [AppService], 8 | }) 9 | export class AppModule {} 10 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { Resource1Created } from './incomingEvents/Resource1Created.event'; 3 | 4 | @Injectable() 5 | export class AppService { 6 | getHello(): string { 7 | return 'Hello World!'; 8 | } 9 | 10 | handleResource1Created(data: Resource1Created) { 11 | console.log('handled data:', data); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/src/incomingEvents/Resource1Created.event.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ArgumentMetadata, 3 | BadRequestException, 4 | PipeTransform, 5 | } from '@nestjs/common'; 6 | import * as Joi from 'joi'; 7 | 8 | type CreateResource1Dto = { 9 | id: string; 10 | name: string; 11 | }; 12 | 13 | export const PATTERN = 'resource_1_created'; 14 | 15 | export class Resource1Created { 16 | public readonly v: number = 1; 17 | constructor(public readonly data: CreateResource1Dto) {} 18 | } 19 | 20 | const eventSchema = Joi.object({ 21 | data: Joi.object({ 22 | id: Joi.string().required(), 23 | name: Joi.string().required(), 24 | }).unknown(true), 25 | }).unknown(true); 26 | 27 | export class Resource1CreatedValidationPipe implements PipeTransform { 28 | transform(value: Resource1Created, metadata: ArgumentMetadata) { 29 | const result = eventSchema.validate(value); 30 | if (result.error) { 31 | console.log('invalid payload', value); 32 | console.log(result.error.message); 33 | throw new BadRequestException('Invalid Resource1Created event received'); 34 | } 35 | return value; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | import { MicroserviceOptions, Transport } from '@nestjs/microservices'; 4 | 5 | async function bootstrap() { 6 | const app = await NestFactory.createMicroservice( 7 | AppModule, 8 | { 9 | transport: Transport.NATS, 10 | options: { 11 | servers: [process.env.NATS_SERVER || 'nats://nats:4222'], 12 | }, 13 | }, 14 | ); 15 | app.listen(); 16 | } 17 | 18 | bootstrap(); 19 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { INestApplication } from '@nestjs/common'; 3 | import * as request from 'supertest'; 4 | import { AppModule } from './../src/app.module'; 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication; 8 | 9 | beforeEach(async () => { 10 | const moduleFixture: TestingModule = await Test.createTestingModule({ 11 | imports: [AppModule], 12 | }).compile(); 13 | 14 | app = moduleFixture.createNestApplication(); 15 | await app.init(); 16 | }); 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-b/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "ES2021", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true, 14 | "skipLibCheck": true, 15 | "strictNullChecks": false, 16 | "noImplicitAny": false, 17 | "strictBindCallApply": false, 18 | "forceConsistentCasingInFileNames": false, 19 | "noFallthroughCasesInSwitch": false 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | tsconfigRootDir: __dirname, 6 | sourceType: 'module', 7 | }, 8 | plugins: ['@typescript-eslint/eslint-plugin'], 9 | extends: [ 10 | 'plugin:@typescript-eslint/recommended', 11 | 'plugin:prettier/recommended', 12 | ], 13 | root: true, 14 | env: { 15 | node: true, 16 | jest: true, 17 | }, 18 | ignorePatterns: ['.eslintrc.js'], 19 | rules: { 20 | '@typescript-eslint/interface-name-prefix': 'off', 21 | '@typescript-eslint/explicit-function-return-type': 'off', 22 | '@typescript-eslint/explicit-module-boundary-types': 'off', 23 | '@typescript-eslint/no-explicit-any': 'off', 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | pnpm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # OS 15 | .DS_Store 16 | 17 | # Tests 18 | /coverage 19 | /.nyc_output 20 | 21 | # IDEs and editors 22 | /.idea 23 | .project 24 | .classpath 25 | .c9/ 26 | *.launch 27 | .settings/ 28 | *.sublime-workspace 29 | 30 | # IDE - VSCode 31 | .vscode/* 32 | !.vscode/settings.json 33 | !.vscode/tasks.json 34 | !.vscode/launch.json 35 | !.vscode/extensions.json -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18-alpine 2 | WORKDIR /app 3 | COPY . . 4 | RUN yarn 5 | CMD ["yarn", "start:dev"] 6 | EXPOSE 3002 -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/README.md: -------------------------------------------------------------------------------- 1 |

2 | Nest Logo 3 |

4 | 5 | ## Description 6 | 7 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. 8 | 9 | ## Installation 10 | 11 | ```bash 12 | yarn install 13 | ``` 14 | 15 | ## Running the app 16 | 17 | ```bash 18 | # development 19 | yarn run start 20 | 21 | # watch mode 22 | yarn run start:dev 23 | 24 | # production mode 25 | yarn run start:prod 26 | ``` 27 | 28 | ## Test 29 | 30 | ```bash 31 | # unit tests 32 | yarn run test 33 | 34 | # e2e tests 35 | yarn run test:e2e 36 | 37 | # test coverage 38 | yarn run test:cov 39 | ``` 40 | 41 | ## Support 42 | 43 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). 44 | 45 | ## Stay in touch 46 | 47 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) 48 | - Website - [https://nestjs.com](https://nestjs.com/) 49 | - Twitter - [@nestframework](https://twitter.com/nestframework) 50 | 51 | ## License 52 | 53 | Nest is [MIT licensed](LICENSE). 54 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src", 5 | "compilerOptions": { 6 | "deleteOutDir": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/src/app.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | 5 | describe('AppController', () => { 6 | let appController: AppController; 7 | 8 | beforeEach(async () => { 9 | const app: TestingModule = await Test.createTestingModule({ 10 | controllers: [AppController], 11 | providers: [AppService], 12 | }).compile(); 13 | 14 | appController = app.get(AppController); 15 | }); 16 | 17 | describe('root', () => { 18 | it('should return "Hello World!"', () => { 19 | expect(appController.getHello()).toBe('Hello World!'); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | import { AppService } from './app.service'; 3 | import { MessagePattern } from '@nestjs/microservices'; 4 | 5 | @Controller() 6 | export class AppController { 7 | constructor(private readonly appService: AppService) {} 8 | 9 | @MessagePattern('get_version') 10 | getVersion() { 11 | return process.env.VERSION || '0.0.21'; 12 | } 13 | 14 | @MessagePattern('get_hello') 15 | getHello() { 16 | return this.appService.getHello(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | 5 | @Module({ 6 | imports: [], 7 | controllers: [AppController], 8 | providers: [AppService], 9 | }) 10 | export class AppModule {} 11 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | getHello(): string { 6 | return 'Hello World From Service C!'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { Transport } from '@nestjs/microservices'; 3 | import { AppModule } from './app.module'; 4 | 5 | async function bootstrap() { 6 | const app = await NestFactory.create(AppModule); 7 | app.connectMicroservice({ 8 | transport: Transport.NATS, 9 | options: { 10 | servers: [process.env.NATS_SERVER || 'nats://nats:4222'], 11 | }, 12 | }); 13 | await app.startAllMicroservices(); 14 | await app.listen(3001); 15 | } 16 | 17 | bootstrap(); 18 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { INestApplication } from '@nestjs/common'; 3 | import * as request from 'supertest'; 4 | import { AppModule } from './../src/app.module'; 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication; 8 | 9 | beforeEach(async () => { 10 | const moduleFixture: TestingModule = await Test.createTestingModule({ 11 | imports: [AppModule], 12 | }).compile(); 13 | 14 | app = moduleFixture.createNestApplication(); 15 | await app.init(); 16 | }); 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /examples/nest-nats-microservices/service-c/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "ES2021", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true, 14 | "skipLibCheck": true, 15 | "strictNullChecks": false, 16 | "noImplicitAny": false, 17 | "strictBindCallApply": false, 18 | "forceConsistentCasingInFileNames": false, 19 | "noFallthroughCasesInSwitch": false 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/stripe-integration-node-typescript/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | /dist 3 | /node_modules 4 | /coverage -------------------------------------------------------------------------------- /examples/stripe-integration-node-typescript/.node-version: -------------------------------------------------------------------------------- 1 | v18.17.0 2 | -------------------------------------------------------------------------------- /examples/stripe-integration-node-typescript/jest.config.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "roots": [ 3 | "/src" 4 | ], 5 | "testMatch": [ 6 | "**/__tests__/**/*.+(ts|tsx|js)", 7 | "**/?(*.)+(spec|test).+(ts|tsx|js)" 8 | ], 9 | "transform": { 10 | "^.+\\.(ts|tsx)$": "ts-jest" 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /examples/stripe-integration-node-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stripe-node-typescript-example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "dist/app.js", 6 | "scripts": { 7 | "dev": "tsc && nodemon dist/app.js", 8 | "test": "jest --verbose", 9 | "test:watch": "jest --watch", 10 | "test:cov": "jest --coverage" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "MIT", 15 | "devDependencies": { 16 | "@types/express": "^4.17.1", 17 | "typescript": "^5.1.6" 18 | }, 19 | "dependencies": { 20 | "@types/jest": "^29.5.3", 21 | "dotenv": "^16.3.1", 22 | "express": "^4.19.2", 23 | "jest": "^29.6.1", 24 | "nodemon": "^2.0.22", 25 | "stripe": "^12.11.0", 26 | "zod": "^3.22.3", 27 | "ts-jest": "^29.1.1", 28 | "ts-node": "^10.9.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/stripe-integration-node-typescript/src/core/stripe/clients/StripeClient.ts: -------------------------------------------------------------------------------- 1 | import Stripe from 'stripe'; 2 | 3 | // stripe instance singleton 4 | const getStripeClient = (() => { 5 | let stripe: Stripe; 6 | return () => { 7 | if (!stripe) { 8 | stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { 9 | apiVersion: '2022-11-15', 10 | }); 11 | } 12 | return stripe; 13 | }; 14 | })(); 15 | 16 | export default { 17 | getStripeClient, 18 | }; 19 | -------------------------------------------------------------------------------- /examples/stripe-integration-node-typescript/src/core/stripe/clients/__tests__/StripeClient.test.ts: -------------------------------------------------------------------------------- 1 | import Stripe from 'stripe'; 2 | import StripeClient from '../StripeClient'; 3 | 4 | // Mock the 'stripe' module 5 | jest.mock('stripe'); 6 | 7 | describe('StripeClient', () => { 8 | // Set up mock environment variables 9 | process.env.STRIPE_SECRET_KEY = 'fake_secret_key'; 10 | 11 | // Set the mock data for the getStripeClient function 12 | const stripeClientParams = { 13 | apiVersion: '2022-11-15', 14 | }; 15 | 16 | afterEach(() => { 17 | jest.clearAllMocks(); 18 | }); 19 | 20 | it('getStripeClient should create a single Stripe instance', () => { 21 | // Call the getStripeClient function 22 | const stripeClient = StripeClient.getStripeClient(); 23 | 24 | // Assert that Stripe constructor is called with the correct arguments 25 | expect(Stripe).toHaveBeenCalledWith(process.env.STRIPE_SECRET_KEY, stripeClientParams); 26 | 27 | // Assert that the returned stripeClient is the same instance created in the first call 28 | expect(stripeClient).toBe(StripeClient.getStripeClient()); 29 | 30 | // Assert that Stripe constructor is called only once when singleton already exists 31 | expect(Stripe).toHaveBeenCalledTimes(1); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /examples/stripe-integration-node-typescript/src/core/stripe/schemas/checkoutParams.schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | 3 | 4 | export const LineItemSchema = z.object({ 5 | price: z.string(), 6 | quantity: z.number() 7 | }); 8 | 9 | // values from Stripe.Checkout.SessionCreateParams.Mode 10 | export const PaymentModesSchema = z.union([ 11 | z.literal('payment'), 12 | z.literal('setup'), 13 | z.literal('subscription'), 14 | ]); 15 | 16 | export const CheckoutParamsSchema = z.object({ 17 | customerId: z.optional(z.string()), 18 | email: z.optional(z.string().email()), 19 | lineItems: z.array(LineItemSchema).nonempty(), 20 | paymentMethod: PaymentModesSchema, 21 | createCustomer: z.optional(z.boolean()), 22 | }).superRefine((schema, ctx) => { 23 | if (schema.customerId && schema.email) { 24 | ctx.addIssue({ 25 | code: z.ZodIssueCode.custom, 26 | message: 'Data must have either a customerId or an email, not both.', 27 | }); 28 | } 29 | if (schema.customerId && schema.createCustomer !== undefined) { 30 | ctx.addIssue({ 31 | code: z.ZodIssueCode.custom, 32 | message: 'CreateCustomer should not be defined if a customerId is sent.', 33 | }); 34 | } 35 | if (schema.customerId === undefined && schema.createCustomer === undefined) { 36 | ctx.addIssue({ 37 | code: z.ZodIssueCode.custom, 38 | message: 'CreateCustomer must be defined if a customerId is not sent.', 39 | }); 40 | } 41 | }); 42 | -------------------------------------------------------------------------------- /examples/stripe-integration-node-typescript/src/core/stripe/types/StripeCheckoutParams.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { CheckoutParamsSchema } from "../schemas/checkoutParams.schema"; 3 | 4 | export type StripeCheckoutParams = z.infer; 5 | -------------------------------------------------------------------------------- /examples/stripe-integration-node-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "esModuleInterop": true, 5 | "target": "es6", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "outDir": "dist" 9 | }, 10 | "lib": ["es2015"] 11 | } 12 | -------------------------------------------------------------------------------- /tools/danger/.node-version: -------------------------------------------------------------------------------- 1 | v16.13.2 2 | -------------------------------------------------------------------------------- /tools/danger/.nvmrc: -------------------------------------------------------------------------------- 1 | v16.13.2 2 | -------------------------------------------------------------------------------- /tools/danger/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend-reference", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "directories": { 7 | "example": "examples" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/nanlabs/backend-reference.git" 15 | }, 16 | "author": "ulises-jeremias", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/nanlabs/backend-reference/issues" 20 | }, 21 | "homepage": "https://github.com/nanlabs/backend-reference#readme", 22 | "devDependencies": { 23 | "danger": "^11.1.1" 24 | } 25 | } 26 | --------------------------------------------------------------------------------