├── .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 | [](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 |
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 |
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 |
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 |
--------------------------------------------------------------------------------