GithubHelp home page GithubHelp logo

juicycleff / ultimate-backend Goto Github PK

View Code? Open in Web Editor NEW
2.5K 70.0 397.0 7.59 MB

Multi tenant SaaS starter kit with cqrs graphql microservice architecture, apollo federation, event source and authentication

Home Page: https://juicycleff.github.io/ultimate-backend-docs

License: MIT License

Dockerfile 0.40% TypeScript 98.97% HCL 0.30% Shell 0.33%
graphql boilerplate cqrs apollo-federation event-sourcing ddd-architecture cqrs-architectural-pattern graphql-server eventstore eventstream

ultimate-backend's Introduction

ULTIMATE BACKEND

(WIP): This is an enterprise scale advanced microservice pattern with GraphQL API and GRPC Microservices, based on Domain (DDD) using the command query responsibility segregation (CQRS) design pattern. Want to ask Rex Isaac Raphael questions, join the slack channel :)

License Snyk Code Size Version Top Language Top Language

Description

Note: The current boilerplate repo is here WIP Ultimate Backend Boilerplate. This repo is currently houses the microservice packages Next Branch.

This should be the go to backend base for your next scalable project. This is a proof of concept project designed to be extremely slim and scalable, with distributed data request and process handling, built from the ground up for production use. It comes with Multi-Tenancy SaaS support, following different multi-tenancy database strategy as well as different resolver patterns
to identify your tenants. The goal is to give your next big project that extra leap to awesomeness. To get started read the instructions below. With support for both Event Store and NATS Streaming for event streaming and Kafka comming soon.

Note: Seeing alot of clone of the project which is good, but please if you can ๐ŸŒŸ the project as it also motivates me in improving the project. Also the docker azure CI setups is broken and will be fixed soon.

Note: Also ultimate backend is coming to rust as a complete microservice framework, if you want to be part of it and you program in rust, please write to me. Here is the repo ultimate

Features

Software features

  • โœ… CQRS
  • โœ… Software as a Service
  • โœ… Authentication by stateful session (Password) GraphQL
  • โœ… OAuth2 Authentication (Google, Github, Facebook) REST
  • โœ… User
  • โœ… Event Sourcing
  • โœ… GraphQL API
  • โœ… GRPC Microservice
  • โœ… Emailing Queue
  • โœ… Role Based Access Control
  • โœ… Multi Tenancy
  • โœ… Payment (Stripe)
  • โœ… SaaS Plans (Stripe)
  • โœ… Security
  • โœ… Service Discovery (Default on Consul), supports ectd, Kubernetes
  • โœ… React SSR Starter Kit
  • โŒ (WiP) Documentation
  • โœ… (WiP) Webhooks
  • โŒ (WiP) Support for language translation
  • โŒ (WiP) GraphQL dataloaders

Software stack

Required Optional
Store and cache Event Store (Event Source Store), Redis (Queue & cache) and MongoDB (Database) ArangoDB (Database), NATS Streaming (Event Source Store)
Stack and frameworks NestJS (Server Framework), NodeJS (System runtime), Typescript, Express JS, Fastify, GRPC, NestCloud and Apollo GraphQL none
Deployment and containerization Docker Kubernetes, Azure Pipeline, GitLab CI
Service Registry Consul Kubernetes and etcd

Folder Structure

Senior candidate in the folder structure is the /app folder. This folder contains all executable programs or in this case microservices

  • /app/service-access The access microservice handles access token management for each tenant in the system. It also validates current tenant credentials against a tenant specific resources. It is the gate keeper for your tenant api.
  • /app/service-account The account microservice handles user account commands and queries such as creating and validating new and current users in the system.
  • /app/service-tenant The tenant microservice handles creating new tenants as well as managing tenant specific commands and queries.
  • /app/service-role Similar to service-access, this service validates users based on roles against the entire system and tenants they belong to. This service handles only user authorization, where service-access is for tenant access keys for external api.
  • /app/service-notification The microservice performs notification tasks in the entire systems. Right now it supports emailing, but can be extended to support push notification as well as activity feeds.
  • /app/service-billing The billing microservice manages billing and payment commands. It is tightly integrated with Stripe, but can be easily replaced.
  • /app/service-project This microservice is merely an example of supporting multi-tenant database strategy. It holds no other significance.

The next important folder is the /lib folder. This folder contains all internal libraries that is depended upon by the microservices, and they are,

  • /lib/common House shared/common modules in the project.
  • /lib/core This is the core module of ultimate backend and houses most of the codebase that wires everything together.
  • /lib/repo-orm This library will be extracted in the future as it matures. It is aimed at being a simple, less cluttered NoSQL multi-tenant object relational mapper (ORM), It supports caching, MongoDB and ArangoDB, with support for FaunaDB in the works.
  • /lib/contracts Shared contracts for both typescript typings and graphql code first types, are stored here.
  • /lib/repository It holds all repositories used in the microservices, and this repository and created from the repo-rom library.
  • /lib/proto-schema All GRPC protobuf files required by each service, is stored in here and shared amongst services that depends on them.

Other folders such as iac which simply means Infrastructure as Code is teraform setup for creating a kubernetes cluster with just a simple command for running the microservices. scripts contains helper bash scripts for CI/CD.

Installation

$ yarn install

Configuration

Before starting the services, please create the appropriate consul (Default service registry Consul) kv store config for all the services. You can find the example config
in the folders of each service called config.example. The consul config key of say the account service should be
ultimatebackend/config/io.ultimatebackend.srv.account and just paste the config.yaml content in the consul store for that key in yaml and save.
You will need to set your sendgrid api key, so the backend can send emails on signup etc. If using stripe for payments you'll also need to put your public and private keys there too.
You can opt in for etcd or kubernetes as service registry.

Usage

With Docker locally

$ docker-compose --project-directory=. -f docker-compose.dev.yml up --build

Note: I've seen some issues with consul docker image and so would recommend setting up consul manually before running this command

Without Docker locally

Consul, Mongodb, redis, memcached, and eventstore all need to be started first as our microservices need to connect to them.

Start consul locally

consul agent --dev  

For help installing consul on your local machine, visit Consul Website

Start mongodb locally

mongod  

If you have docker installed

docker run -d -p 27017:27017 mongo  
docker run -d -p 1113:1113 -p 2113:2113 eventstore/eventstore --insecure # insecure flag specifies no certificate required - suitable for devmode 
docker run -d -p 6379:6379 redis  

Otherwise, you can install and run redis and eventstore locally if you choose.

Running the microservices

You should start the microservices in any other. Example

  
# Generate protobuf typescript definitions and please fix the path for timestamps import (You should do this only when you update the protobuf files)
# and also build the proto-scheme lib (You should do this only when you update the protobuf files)
# in `lib/proto-schem`
# Also adds configuration(config.example files) to consul K/V registry (consul need to be running)
# You need jq and yq programs to use it   
$ yarn setup:local
  
# Start the account service  
$ npx nest start service-account  
  
# Start the access service  
$ npx nest start service-access  
  
# Start the role service  
$ npx nest start service-role  
  
# Start the graphql api  
$ npx nest start api-admin  
  

Note: You don't need all services running plus you can start them in any order.

Alternative method of running services

If you find the nest cli using too much memory running each service, you can build them first and then run them:

Build each service:

npx nest build service-account  
npx nest build service-notification  
npx nest build service-billing  
npx nest build service-project  
npx nest build service-tenant  
npx nest build service-access  
npx nest build service-role  

Each service is built and written into dist/apps directory from where you can directly run each service with nodejs. Running each service with npx nest start uses three orders of magnitude more memory than this method so you will use a lot less memory!

Run each service in a separate terminal:

node dist/apps/service-account/main.js  
node dist/apps/service-notification/main.js  
node dist/apps/service-billing/main.js  
node dist/apps/service-project/main.js  
node dist/apps/service-tenant/main.js  
node dist/apps/service-access/main.js  

With the databases and the services running you can now start the gateways as mentioned above.

yarn start:dev api-admin  

Get started by registering a user on the admin gateway

In the graphql playground running at http://localhost:4000//graph you can register a user:

mutation register {  
  account {  
    register(input:{  
        firstname: "Alice"  
        lastname: "Bob"  
        email: "[email protected]"  
        password: "supersecretpassword"  
    }) {  
      token  
    }  
  }  
}  

All going well you should have received the following reply as well as an email with a verification code as well as a jwt token that contains both email and verification code for your frontend

{  
    "data": {  
        "account": {  
            "register": {  
                "token": "gtdjghdrtd65edjhc-chxgfxjtgzrkzxyzxtrs45wi6kydch"  
            }  
        }  
    }  
}  

Quick Tips

Generating dynamic mongo filter GraphQL type.

You can generate dynamic graphql filter by decorating the fields you want to be
avaiable in your generated filter type with the @Filterable() decorator like below

import { Filterable } from '@ultimatebackend/core';  
  
@ObjectType()  
export class Tenant extends Node {  
  
  @Filterable()  
  @Field({ nullable: true })  
  name: string;  
  
  @Filterable()  
  @Field({ nullable: true })  
  normalizedName: string;  
}  

After adding decorator to the fields you can now add generate your graphql input type.

Note: Enums and sub-types not supported at the moment.

import { FilterMongo } from '@ultimatebackend/contracts';  
  
@InputType()  
export class TenantFilterInput extends FilterMongo(Tenant, { simple: true }) {}  

Multi-tenant Database for services.

You can enable multi-tenant database support in your micro-service by adding this

MongoModule.registerAsync({  
 useClass: MongoMultiTenantConfigService,  
})

code block to the service app module. For example;

import { Module } from '@nestjs/common';  
import { MongoModule } from '@juicycleff/repo-orm/database';  
import { MongoMultiTenantConfigService } from '@ultimatebackend/core/mutiltenancy';  
  
@Module({  
  imports: [
    // ...
    MongoModule.registerAsync({  
      useClass: MongoMultiTenantConfigService,  
    }),
    // ...
  ],  
})  
export class AppModule {}  

A good example is the service-project microservice.

Next you must enable multi-tenancy in the main.ts file of the api-admin service or any other api type microservice you create in your project.

import { NestFactory } from '@nestjs/core';  
import { NestCloud } from '@nestcloud/core';  
import { AppModule } from './app.module';  
import { enableMultiTenancy, TenantDatabaseStrategy } from '@ultimatebackend/core/mutiltenancy';  
  
async function bootstrap() {  
  const app = NestCloud.create(await NestFactory.create(AppModule));  
  
  app.use(enableMultiTenancy({  
    enabled: true,  
    tenantResolver: {  
      resolverType: 'Header',  
      headerKeys: {  
        tenant: 'x-tenant-id',  
        apiKey: 'x-tenant-key',  
      },  
      requiresToken: true,  
    },  
    databaseStrategy: TenantDatabaseStrategy.DataIsolation,  
  }));  
  
  // ..... code continues  
}  
  

Access token with scopes

Access tokens scopes just a combination of action and resource identifier. For example, take this mutation;

  @UseGuards(GqlAuthGuard)
  @Resource({ name: 'billing', identify: 'billing:card', roles: ['customer'], action: 'update' })
  @ResolveField(() => Card)
  async create(@Args('input') input: CreateCardInput, @Context() ctx: GqlContext): Promise<Card> {
    // @ts-ignore
    const result = await this.service.billing.createCard({...input}, setRpcContext(ctx)).toPromise();
    return result.card;
  }

Your access token scope will be update_billing:card and so your mutation to create an access token should look like this

mutation {
  accessToken {
    create(input: {
      name: "my-superb-token",
      scopes: ["update_billing:card"]
    }) {
      token
      id
      name
      active
    }
  }
}

That's all you need to know when creating access token which should be used together with your tenant normalized name to access the API without a logged in user.

More docs updates coming.

Test

# unit tests  
$ yarn run test  
  
# e2e tests  
$ yarn run test:e2e  
  
# test coverage  
$ yarn run test:cov  

Financial Contributors

Become a financial contributor. Your funds go to; people in need [Contribute]

Backers

Sponsors

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

My Other Projects

Here are some of my projects, show some love and start them if you find them helpful :)

Special Thanks

This project wouldn't be possible without these two awesome projects, NestJS (Server Framework) and NestCloud, please make sure to Star them.

License

This project is MIT licensed.

ultimate-backend's People

Contributors

0xb4lamx avatar dependabot[bot] avatar idshdx avatar juicycleff avatar mtrimolet avatar snyk-bot avatar suadik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ultimate-backend's Issues

Dockerfile redundancy

There's a redundancy in the Dockerfiles:

FROM node:12-alpine
# [...]
ADD . /nest
WORKDIR /nest
# [...]
# /!\ App source is already bundled
COPY . .

EXPOSE 50020
CMD ["node", "dist/apps/api-admin/main.js"]

I'd prepend the COPY with a FROM instruction to have the service run in a minimal environment.

Runtime Error (service-notification) : EmailModule BRPOPLPUSH ReplyError

version : 2.0.0-alpha.2

nest start service-notification gives an error after startup from EmailModule

BRPOPLPUSH ReplyError: READONLY You can't write against a read only replica.
at parseError (D:\Projects\iBAP-Omnicom\NEST\ultimate-backend\node_modules\redis-parser\lib\parser.js:179:12)
at parseType (D:\Projects\iBAP-Omnicom\NEST\ultimate-backend\node_modules\redis-parser\lib\parser.js:302:14) {
command: {
name: 'brpoplpush',
args: [
'bull:notification_queue:wait',
'bull:notification_queue:active',
'5'
]
}
}

Schema must contain uniquely named types but contains multiple types named "EmailObject".

Hello. There is an error while running api-admin service regarding the EmailObject type.
Any possible fixes ?

(node:3244) UnhandledPromiseRejectionWarning: Error: Schema must contain uniquely named types but contains multiple types named "EmailObject".
    at new GraphQLSchema (C:\Users\msi4\apps\ultimate-backend\node_modules\graphql\type\schema.js:194:15)
    at GraphQLSchemaFactory.<anonymous> (C:\Users\msi4\apps\ultimate-backend\node_modules\@nestjs\graphql\dist\schema-builder\graphql-schema.factory.js:41:32)
    at Generator.next (<anonymous>)
    at C:\Users\msi4\apps\ultimate-backend\node_modules\@nestjs\graphql\node_modules\tslib\tslib.js:114:75
    at new Promise (<anonymous>)
    at Object.__awaiter (C:\Users\msi4\apps\ultimate-backend\node_modules\@nestjs\graphql\node_modules\tslib\tslib.js:110:16)
    at GraphQLSchemaFactory.create (C:\Users\msi4\apps\ultimate-backend\node_modules\@nestjs\graphql\dist\schema-builder\graphql-schema.factory.js:30:28)
    at GraphQLSchemaBuilder.<anonymous> (C:\Users\msi4\apps\ultimate-backend\node_modules\@nestjs\graphql\dist\graphql-schema.builder.js:57:60)
    at Generator.next (<anonymous>)
    at C:\Users\msi4\apps\ultimate-backend\node_modules\@nestjs\graphql\node_modules\tslib\tslib.js:114:75
    at new Promise (<anonymous>)
    at Object.__awaiter (C:\Users\msi4\apps\ultimate-backend\node_modules\@nestjs\graphql\node_modules\tslib\tslib.js:110:16)
    at GraphQLSchemaBuilder.buildSchema (C:\Users\msi4\apps\ultimate-backend\node_modules\@nestjs\graphql\dist\graphql-schema.builder.js:56:28)
    at GraphQLSchemaBuilder.<anonymous> (C:\Users\msi4\apps\ultimate-backend\node_modules\@nestjs\graphql\dist\graphql-schema.builder.js:26:39)
    at Generator.next (<anonymous>)
    at C:\Users\msi4\apps\ultimate-backend\node_modules\@nestjs\graphql\node_modules\tslib\tslib.js:114:75
(node:3244) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:3244) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Relevant issues
MichalLytek/type-graphql#396
nestjs/graphql#721

Multi Database Generic Interface Support

We can discuss on the topic of ORM and database choices. We can talk about support for database from column wide database to graph databases, keep insight a features that can be added and even improved in the boilerplate

Consul Connection Refused

When I run the docker-compose command to build the services locally, each of the services output:

Error: consul: kv.get: connect ECONNREFUSED 127.0.0.1:8500

Any ideas why?

Eventstore version

Latest version from eventstore is based in release 20.6.0. This release needs an enviroment variable to use http (release 20.6.0 use https):

    environment:
      - EVENTSTORE_DEV=true

I'm fixing image in my docker-compose to image: eventstore/eventstore:release-5.0.8 , since I'm still trying to makes my dev enviroment to works (run it using vscode node.js debug terminal first, and afte run docker version in debug mode).

Docker not building api-admin

Hello, thanks for this amazing proof of concept. I am considering of using it in our next big project. But having difficulty with running project locally via docker-compose.

$ docker-compose --project-directory=. -f docker-compose.dev.yml up --build
Building api-admin
Step 1/15 : FROM node:12-alpine
 ---> 1c342643aa5c
Step 2/15 : ARG NODE_ENV=production
 ---> Using cache
 ---> d96d53c896f6
Step 3/15 : ENV NODE_ENV $NODE_ENV
 ---> Using cache
 ---> 2be4f126daef
Step 4/15 : ARG NODE_OPTIONS=--max_old_space_size=4096
 ---> Using cache
 ---> f959a425712a
Step 5/15 : ENV NODE_OPTIONS $NODE_OPTIONS
 ---> Using cache
 ---> 967aa219d20d
Step 6/15 : RUN mkdir -p /nest
 ---> Using cache
 ---> 0de7b5663b67
Step 7/15 : ADD . /nest
 ---> Using cache
 ---> 8aea53b3bf31
Step 8/15 : WORKDIR /nest
 ---> Using cache
 ---> f635447004b8
Step 9/15 : RUN yarn global add @nestjs/cli
 ---> Using cache
 ---> fdaea75ef8c9
Step 10/15 : RUN yarn install --production=false
 ---> Running in 4eea7f95a445
yarn install v1.22.4
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning "@apollo/gateway > [email protected]" has incorrect peer dependency "graphql@^14.2.1".
warning "@apollo/gateway > apollo-server-core > [email protected]" has incorrect peer dependency "graphql@^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0".
warning "apollo-server > [email protected]" has incorrect peer dependency "graphql@^0.13.0 || ^14.0.0".
warning "@apollo/gateway > apollo-server-core > [email protected]" has incorrect peer dependency "[email protected] - 14".
warning "@apollo/gateway > apollo-server-core > graphql-tools > [email protected]" has incorrect peer dependency "graphql@^0.11.3 || ^0.12.3 || ^0.13.0 || ^14.0.0".
warning "@apollo/gateway > apollo-server-core > graphql-tools > [email protected]" has incorrect peer dependency "graphql@^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has unmet peer dependency "consul@^0.34.1".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has unmet peer dependency "consul@^0.30.0".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/microservices@^6.1.1".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has unmet peer dependency "kubernetes-client@^8.3.3".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestcloud/[email protected]" has unmet peer dependency "consul@^0.34.1".
warning " > @nestjs/[email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > @nestjs/[email protected]" has incorrect peer dependency "@nestjs/core@^6.0.0".
warning " > @nestjs/[email protected]" has incorrect peer dependency "[email protected]".
warning "apollo-server > [email protected]" has incorrect peer dependency "graphql@^0.10.5 || ^0.11.3 || ^0.12.0 || ^0.13.0 || ^14.0.0".
warning " > [email protected]" has unmet peer dependency "[email protected]".
warning " > [email protected]" has unmet peer dependency "[email protected] || 6.x".
warning " > [email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > [email protected]" has incorrect peer dependency "@nestjs/core@^6.0.0".
warning " > [email protected]" has incorrect peer dependency "@nestjs/common@^6.0.0".
warning " > [email protected]" has incorrect peer dependency "@nestjs/core@^6.0.0".
warning " > [email protected]" has incorrect peer dependency "stripe@^8.0.0".
warning " > [email protected]" has incorrect peer dependency "graphql@^14.6.0".
warning "type-graphql > [email protected]" has incorrect peer dependency "graphql@^0.13.0 || ^14.0.0".
[4/4] Building fresh packages...
$ yarn run snyk-protect
yarn run v1.22.4
$ snyk protect
Successfully applied Snyk patches

Done in 130.38s.
Done in 391.39s.
Removing intermediate container 4eea7f95a445
 ---> a2dbbc51c37b
Step 11/15 : RUN nest build proto-schema
 ---> Running in 0532669ee88d
Starting type checking service...
Gracefully stopping... (press Ctrl+C again to force)
Hash: f3d3ce9cc5014f105899
Version: webpack 4.42.1
Time: 293934ms
Built at: 06/06/2020 2:29:53 PM
Entrypoint main = libs/proto-schema/index.js
Removing intermediate container 0532669ee88d
 ---> 1e7364a6604c
Step 12/15 : RUN nest build api-admin
 ---> Running in 29cd462f0c61
Starting type checking service...

Then the process just hands there and nothing happens. Not sure if repo issue or just doing something wrong. Any advice ?

Deploy to GCP

Can you add a guide on how to successfully deploy to google cloud platform?

Event-Source - Alternatives?

Hi

Firstly - awesome repo! Think this is really impressive.

I wanted to ask - is there flexibility to use an alternative to event-store?

What is supported in terms of using alternative event stores? i see you have type: 'event-store'. If this was replaced with say 'nats' would you get the same functionality?

Thank you

DollarPrefixedFieldName - MongoDB error

When running the project and following the steps i came across an issue with findOneAndUpdate in the base-mongo.repository.ts located in the repo-orm lib.

When executing the code it complained with this error:

[Nest] 44633 - [RegisterUserHandler] Object:
{
"ok": 0,
"code": 52,
"codeName": "DollarPrefixedFieldName",
"name": "MongoError"
}

To get this working, i changed the it from { $set: { ...req.updates } } to { ...req.updates }

from:

 async findOneAndUpdate(req: UpdateRequest): Promise<DOC> {
    const collection = await this.collection;
    const updates = await this.invokeEvents(
      PRE_KEY,
      ['UPDATE', 'UPDATE_ONE'],
      { $set: { ...req.updates } },
    );

to:

 async findOneAndUpdate(req: UpdateRequest): Promise<DOC> {
    const collection = await this.collection;
    const updates = await this.invokeEvents(
      PRE_KEY,
      ['UPDATE', 'UPDATE_ONE'],
      { ...req.updates },
    );

Hope this is helpful

INTERNAL_SERVER_ERROR at register query

Hello. I am using docker to load up the project. Currently facing an issue with registering a user via graphql API.
My query looks like this

# Write your query or mutation here
mutation register {  
  account {  
    register(input:{  
        firstname: "Alice"  
        lastname: "Bob"  
        email: "[email protected]"  
        password: "supersecretpassword"  
    }) {  
      activationLink  
    }  
  }  
}  

Response object

{
  "errors": [
    {
      "message": "Cannot read property 'id' of null",
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ],
      "path": [
        "account",
        "register"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "TypeError: Cannot read property 'id' of null",
            "    at GrpcClient.getProxyService (/nest/node_modules/@nestcloud/grpc/grpc-client.js:37:35)",
            "    at Object.grpcService.<computed> [as create] (/nest/node_modules/@nestcloud/grpc/grpc-client.js:19:46)",
            "    at AccountsMutationResolver.register (/nest/dist/apps/api-admin/main.js:12770:62)",
            "    at /nest/node_modules/@nestjs/core/helpers/external-context-creator.js:68:33",
            "    at processTicksAndRejections (internal/process/task_queues.js:97:5)",
            "    at async target (/nest/node_modules/@nestjs/core/helpers/external-context-creator.js:75:28)"
          ]
        }
      }
    }
  ],
  "data": {
    "account": null
  }
}

Not sure if it's related but my consul docker container seems to have troubles connecting to agents

consul                  |     2020-06-12T13:44:43.328Z [WARN]  agent: Check socket connection failed: check=service:61c57d32688b99dc1b32ec8954384224 error="dial tcp 172.18.0.7:50054: connect: connection refused"
consul                  |     2020-06-12T13:44:43.328Z [WARN]  agent: Check is now critical: check=service:61c57d32688b99dc1b32ec8954384224
consul                  |     2020-06-12T13:44:44.458Z [WARN]  agent: Check socket connection failed: check=service:e7dbeff530ad82853d5dd9dccf9e2713 error="dial tcp 172.18.0.7:50044: connect: connection refused"
consul                  |     2020-06-12T13:44:44.458Z [WARN]  agent: Check is now critical: check=service:e7dbeff530ad82853d5dd9dccf9e2713
consul                  |     2020-06-12T13:44:45.009Z [WARN]  agent: Check socket connection failed: check=service:81e00fbd54edafc9977a46de2d83b416 error="dial tcp 172.18.0.7:45543: connect: connection refused"
consul                  |     2020-06-12T13:44:45.010Z [WARN]  agent: Check is now critical: check=service:81e00fbd54edafc9977a46de2d83b416
consul                  |     2020-06-12T13:44:48.872Z [WARN]  agent: Check socket connection failed: check=service:5758287bf77407520711c974a1aafa1e error="dial tcp 172.18.0.7:4000: connect: connection refused"
consul                  |     2020-06-12T13:44:48.873Z [WARN]  agent: Check is now critical: check=service:5758287bf77407520711c974a1aafa1e
consul                  |     2020-06-12T13:44:48.952Z [WARN]  agent: Check socket connection failed: check=service:92265306afe150a099f226b4df63b88d error="dial tcp 172.18.0.7:50089: connect: connection refused"
consul                  |     2020-06-12T13:44:48.952Z [WARN]  agent: Check is now critical: check=service:92265306afe150a099f226b4df63b88d
consul                  |     2020-06-12T13:44:52.812Z [WARN]  agent: Check socket connection failed: check=service:b9e675453a37acf83156105fe8b095f6 error="dial tcp 172.18.0.7:50052: connect: connection refused"
consul                  |     2020-06-12T13:44:52.812Z [WARN]  agent: Check is now critical: check=service:b9e675453a37acf83156105fe8b095f6
consul                  |     2020-06-12T13:44:53.330Z [WARN]  agent: Check socket connection failed: check=service:61c57d32688b99dc1b32ec8954384224 error="dial tcp 172.18.0.7:50054: connect: connection refused"
consul                  |     2020-06-12T13:44:53.330Z [WARN]  agent: Check is now critical: check=service:61c57d32688b99dc1b32ec8954384224

Any ideas what cause this ?

Helper script bug (register.sh)

This is the output that i get from running register.sh It is expected write configs for all the services, yet it only does so for service-project.

$ ./scripts/register.sh
Service Registration system started
/src/bootstrap.yaml not found, skipping service
/src/bootstrap.yaml not found, skipping service
/src/bootstrap.yaml not found, skipping service
/src/bootstrap.yaml not found, skipping service
/src/bootstrap.yaml not found, skipping service
/src/bootstrap.yaml not found, skipping service
/src/bootstrap.yaml not found, skipping service
Registering io.ultimatebackend.srv.project
Success! Data written to: ultimatebackend/config/io.ultimatebackend.srv.project
Service Registration system completed

The issue is that PROJECT_DIR variable contains a hidden new line character /r at the end of string.

Horizontal Scaing?

Can each of these services be horizontally scaled? If for example, running in Kubernetes and they have a service to many pods - will it react in the correct way or attempt to duplicate logic ?

Cannot return null for non-nullable field AuthPayload.tokens.

Error while attempting to login

Probably not a bug; I'm not sure I understand yet what I'm supposed to do to login from graphql playground.

I registered with the register mutation

mutation register {
  register(input:{
    firstname: "firstname"
    lastname: "lastname"
    email: "[email protected]"
    password: "supersecretpassword"
  }) {
    success
  }
}

which replied with success: true

Then verified email with

mutation verifyEmail {
  verifyEmail(token: tokenfromsignupemail, email: "[email protected]") {
    success
  }
}

which also replied success. However when I go to login like

mutation login {
  login(input:{
    service: Password
    params:{
      password: "supersecretpassword"
      email: "[email protected]"
    }
  }) {
    id
    sessionId
    tokens {
      refreshToken
      accessToken
    }
  }
}

... I get the following error:

{
  "errors": [
    {
      "message": "Cannot return null for non-nullable field AuthPayload.tokens.",
      "path": [
        "login",
        "tokens"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "serviceName": "auth",
        "query": "mutation {\n  login(input: {service: Password, params: {password: \"supersecretpasswordiused\", email: \"[email protected]\"}}) {\n    id\n    sessionId\n    tokens {\n      refreshToken\n      accessToken\n    }\n  }\n}",
        "variables": {},
        "exception": {
          "stacktrace": [
            "Error: Cannot return null for non-nullable field AuthPayload.tokens.",
            "    at completeValue (/home/av8ta/code/ultimate-backend/node_modules/graphql/execution/execute.js:560:13)",
            "    at completeValueCatchingError (/home/av8ta/code/ultimate-backend/node_modules/graphql/execution/execute.js:495:19)",
            "    at resolveField (/home/av8ta/code/ultimate-backend/node_modules/graphql/execution/execute.js:435:10)",
            "    at executeFields (/home/av8ta/code/ultimate-backend/node_modules/graphql/execution/execute.js:275:18)",
            "    at collectAndExecuteSubfields (/home/av8ta/code/ultimate-backend/node_modules/graphql/execution/execute.js:713:10)",
            "    at completeObjectValue (/home/av8ta/code/ultimate-backend/node_modules/graphql/execution/execute.js:703:10)",
            "    at completeValue (/home/av8ta/code/ultimate-backend/node_modules/graphql/execution/execute.js:591:12)",
            "    at completeValue (/home/av8ta/code/ultimate-backend/node_modules/graphql/execution/execute.js:557:21)",
            "    at /home/av8ta/code/ultimate-backend/node_modules/graphql/execution/execute.js:492:16",
            "    at runMicrotasks (<anonymous>)"
          ]
        }
      }
    }
  ],
  "data": null
}

But a few seconds later I get a User Logged In email. So I try a query:

query me {
  me {
    firstname
  }
}

Which unsurprisingly returns an error:

{
  "errors": [
    {
      "message": "Cannot return null for non-nullable field User.firstname.",
...

Not sure what I'm doing wrong here?

Error: "Cursor" defined in resolvers, but not in schema while running api-admin (2.0.0-alpha.1)

version : 2.0.0-alpha.1

Followed tutorial and after starting all services tried to start api-admin, getting following error

$ node dist/apps/api-admin/main.js
[Nest] 12324 - 04/15/2020, 1:03:14 AM [NestFactory] Starting Nest application...
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] BootModule dependencies initialized +130ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] GlobalClientModule dependencies initialized +3ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] CoreModule dependencies initialized +1ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] PassportModule dependencies initialized +1ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] WebhooksModule dependencies initialized +2ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] NotificationsModule dependencies initialized +1ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] HttpModule dependencies initialized +4ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] PlansModule dependencies initialized +4ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] ConsulModule dependencies initialized +17ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] AppModule dependencies initialized +2ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] RolesModule dependencies initialized +3ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] CqrsModule dependencies initialized +3ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] TenantsModule dependencies initialized +3ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] BillingsModule dependencies initialized +1ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] CardsModule dependencies initialized +2ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] TenantMembersModule dependencies initialized +2ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] UsersModule dependencies initialized +2ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] AccessTokenModule dependencies initialized +2ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] GraphQLSchemaBuilderModule dependencies initialized +2ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [ConfigModule] ConfigModule initialized
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] ConfigModule dependencies initialized +3ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] AccountsModule dependencies initialized +6ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] GraphQLModule dependencies initialized +3ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [ServiceModule] ServiceModule initialized
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] ServiceModule dependencies initialized +5ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [InstanceLoader] LoadbalanceModule dependencies initialized +2ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [RoutesResolver] AppController {}: +165ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [RouterExplorer] Mapped {, GET} route +6ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [RoutesResolver] AccountsController {/account}: +2ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [RouterExplorer] Mapped {/account/facebook, GET} route +4ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [RouterExplorer] Mapped {/account/google, GET} route +2ms
[Nest] 12324 - 04/15/2020, 1:03:14 AM [RouterExplorer] Mapped {/account/github, GET} route +2ms
(node:12324) UnhandledPromiseRejectionWarning: Error: "Cursor" defined in resolvers, but not in schema
(node:12324) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:12324) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Consul configration with docker-compose

@juicycleff hi,

I have just cloned this Repo and creating a build with docker-compose for accounts service with the consul and trying to run.
But I am facing an issue with the accounts service for the consul setting kv.get.
image

I have tried both methods.
1- Setting up the consul manually before running the command docker-compose for a build.
2- And configuration consul in the docker-compose-dev.yaml file.

Butt I am facing the same issue key-value Error: consul: kv.get: connect ECONNREFUSED 127.0.0.1:8500
I am pasting my docker-compose.dev.ymal configuration.

version: "3.2"

services:
  service-account:
    build:
      context: .
      dockerfile: apps/service-account/Dockerfile
      args:
        NODE_ENV: development
    image: "service-account:latest"
    restart: always
    depends_on:
      - consul
      - redis
    environment:
      - CONSUL_HOST=consul
      - NATS_HOST=nats
      - DISCOVERY_HOST=localhost
    ports:
      - 50054:50054
    labels:
      kompose.service.type: clusterip
      kompose.image-pull-secret: "gitlabregcrednew"
      kompose.image-pull-policy: "Always"
   consul:
    container_name: consul
    ports:
      - "8400:8400"
      - "8500:8500"
      - "8600:53/udp"
    image: consul
    command: ["agent", "-server", "-bootstrap", "-ui", "-client", "0.0.0.0"]
    labels:
      kompose.service.type: nodeport
      kompose.service.expose: "true"
      kompose.image-pull-policy: "Always"

  eventstore:
    container_name: eventstore
    ports:
      - "2113:2113"
      - "1113:1113"
    image: eventstore/eventstore:release-5.0.8
    labels:
      kompose.service.type: nodeport
      kompose.service.expose: "true"
      kompose.image-pull-policy: "Always"

  nats:
    container_name: nats
    ports:
      - "4222:4222"
      - "6222:6222"
      - "8222:8222"
    image: nats
    labels:
      kompose.service.type: nodeport
      kompose.service.expose: "true"
      kompose.image-pull-policy: "Always"

  mongo:
    container_name: mongo
    image: mongo
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: changeit
    restart: always
    expose:
      - 27017

  redis:
    container_name: redis
    image: redis
    restart: always
    expose:
      - 6379

My config.example

app:
  port: 9900
  auth:
    jwtSettings:
      secret: "eyJhbGciOiJSUzI1NiIsImtpZCI6Im1hYXNfcHJvZF8yMDIwMDMyNiIsInR5cCI6IkpXVCJ9"
  database:
    name: "srv-account"

database:
  mongodb:
    uri: mongodb://localhost:27017/
    name: srv-account
    options: ""

  eventstore:
    poolMax:
    poolMin:
    streamProtocol: "http"
    hostname: "localhost"
    httpPort: 2113
    httpPotocol: "http"
    tcpPassword: "changeit"
    tcpUsername: "admin"
    tcpPort: 1113
    tcpProtocol: tcp

  redis:
    host: "localhost"
    port: "6379"
    password: ""

Cannot set headers after they are sent to the client

Hello i reduced the code for login page to this.

  @ResolveField(() => Account)
  async login(
    @Args("input") { service, params }: LoginInput,
    @Context() context: any
  ): Promise<Account> {
    const auth = await context.authenticate("graphql-local", {
      email: params.email,
      password: params.password,
    });
    context.login(auth.user);
    return {
      id: auth.user.id,
      user: auth.user,
    };
  }

Yet still i receive and error when i try to login the user. The error disappears when i remove context.login(auth.user) function.

(node:432) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

at ServerResponse.setHeader (_http_outgoing.js:518:11)

at ServerResponse.header (/ftw/node_modules/express/lib/response.js:771:10)

at ServerResponse.send (/ftw/node_modules/express/lib/response.js:170:12)

at ServerResponse.json (/ftw/node_modules/express/lib/response.js:267:15)

at ExpressAdapter.reply (/ftw/node_modules/@nestjs/platform-express/adapters/express-adapter.js:24:57)

at ExceptionsHandler.handleUnknownError (/ftw/node_modules/@nestjs/core/exceptions/base-exception-filter.js:33:24)

at ExceptionsHandler.catch (/ftw/node_modules/@nestjs/core/exceptions/base-exception-filter.js:17:25)

at ExceptionsHandler.next (/ftw/node_modules/@nestjs/core/exceptions/exceptions-handler.js:16:20)

at /ftw/node_modules/@nestjs/core/router/router-proxy.js:24:35

at Layer.handle_error (/ftw/node_modules/express/lib/router/layer.js:71:5)

at trim_prefix (/ftw/node_modules/express/lib/router/index.js:315:13)

at /ftw/node_modules/express/lib/router/index.js:284:7

at Function.process_params (/ftw/node_modules/express/lib/router/index.js:335:12)

at next (/ftw/node_modules/express/lib/router/index.js:275:10)

at Layer.handle_error (/ftw/node_modules/express/lib/router/layer.js:67:12)

at trim_prefix (/ftw/node_modules/express/lib/router/index.js:315:13)

(node:432) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 4)

(node:432) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

What might cause the error ?

TypeError: stripe_1.default is not a constructor

Hello, i get TypeError: stripe_1.default is not a constructor error when starting service-billing. It seems to have something to do either with import or with stripe types in nestjs-stripe package.

service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [NestFactory] Starting Nest application...
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] ServiceRegistryModule dependencies initialized +83ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] LoggerModule dependencies initialized +1ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] ScheduleModule dependencies initialized +0ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] BootModule dependencies initialized +0ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] MemcachedModule dependencies initialized +1ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] EventStoreModule dependencies initialized +0ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] CommonModule dependencies initialized +0ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] CoreModule dependencies initialized +1ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] MongoModule dependencies initialized +0ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] StripeModule dependencies initialized +1ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] EventStoreModule dependencies initialized +1ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] HttpModule dependencies initialized +4ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] AppModule dependencies initialized +1ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] ConsulModule dependencies initialized +1ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] CqrsModule dependencies initialized +10ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [ConfigModule] ConfigModule initialized
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [InstanceLoader] ConfigModule dependencies initialized +1ms
service-billing_1       | [Nest] 1   - 06/13/2020, 4:50:28 AM   [ExceptionHandler] stripe_1.default is not a constructor +18ms
service-billing_1       | TypeError: stripe_1.default is not a constructor
service-billing_1       |     at Object.getStripeClient (/nest/node_modules/nestjs-stripe/lib/util/getStripeClient.js:22:26)
service-billing_1       |     at InstanceWrapper.useFactory [as metatype] (/nest/node_modules/nestjs-stripe/lib/StripeCoreModule.js:27:51)
service-billing_1       |     at Injector.instantiateClass (/nest/node_modules/@nestjs/core/injector/injector.js:292:55)
service-billing_1       |     at callback (/nest/node_modules/@nestjs/core/injector/injector.js:76:41)
service-billing_1       |     at processTicksAndRejections (internal/process/task_queues.js:97:5)
service-billing_1       |     at async Injector.resolveConstructorParams (/nest/node_modules/@nestjs/core/injector/injector.js:117:24)
service-billing_1       |     at async Injector.loadInstance (/nest/node_modules/@nestjs/core/injector/injector.js:80:9)
service-billing_1       |     at async Injector.loadProvider (/nest/node_modules/@nestjs/core/injector/injector.js:37:9)
service-billing_1       |     at async Promise.all (index 5)
service-billing_1       |     at async InstanceLoader.createInstancesOfProviders (/nest/node_modules/@nestjs/core/injector/instance-loader.js:42:9)
service-billing_1       |     at async /nest/node_modules/@nestjs/core/injector/instance-loader.js:27:13
service-billing_1       |     at async Promise.all (index 21)
service-billing_1       |     at async InstanceLoader.createInstances (/nest/node_modules/@nestjs/core/injector/instance-loader.js:26:9)
service-billing_1       |     at async InstanceLoader.createInstancesOfDependencies (/nest/node_modules/@nestjs/core/injector/instance-loader.js:16:9)
service-billing_1       |     at async /nest/node_modules/@nestjs/core/nest-factory.js:81:17
service-billing_1       |     at async Function.asyncRun (/nest/node_modules/@nestjs/core/errors/exceptions-zone.js:17:13)

documentation error - user registration

when i put:

mutation register {
account {
register(input:{
firstname: "Alice"
lastname: "Bob"
email: "[email protected]"
password: "supersecretpassword"
}) {
token
}
}
}

Get:
{
"error": {
"errors": [
{
"message": "Cannot query field "token" on type "AccountRegisterResponse".",
"locations": [
{
"line": 4,
"column": 7
}
],
"extensions": {
"code": "GRAPHQL_VALIDATION_FAILED",
"exception": {
"stacktrace": [
"GraphQLError: Cannot query field "token" on type "AccountRegisterResponse".",

................

        ]
      }
    }
  }
]

}
}

Excessive memory usage using npx nest start service

Firstly, wow this project looks super interesting!

I ran into a snag spinning up each service as suggested in the docs:

NODE_ENV=staging npx nest start service-auth

Each service consumed about 2GB of memory on my poor little machine. With more than half a dozen services to spin up and my machine only having 8GB memory.... ๐Ÿ˜ฑ

It appears to be related to this issue nestjs/nest#2135 where it's established that ts-node is the culprit. tsc-watch is suggested as a solution there. Perhaps that would be a good idea?

I got around the issue by building each service and running them with node from the dist directory however that felt awkward. Digging deeper I realised you're using docker (have used a little), terraform, and kubernetes (have not used either of them). I noticed development configs there alongside staging and production.... so perhaps I've misunderstood and there's a simpler way to manage devops in development?

NEW ARCHITECTURE PROPOSAL

I have a new proposal to change the entire architecture to decoupled services and by that, I mean services not tied to APIs directly. For example, in the current implementation and design, the services are closely tied to GraphQL and that was the plan from the beginning, but moving forward, that will change and doing so we can have better control of our services. and graphql should be one means of talking to the services. below is a diagram of how the new architecture should look like. I would need your contributions is you are willing to share

Ultimate Backend Diagram

Serverless and message queue

Thank you for this great project. I have a some questions:

  1. How coupled it is to docker? I mean, is that possible to go serverless? If so, what do I need to change?
  2. Is there a messaging queue like rabbit mq in the project?

Thanks in advance and keep up the good job!

how to login with return token for auth?

how to login with return token for auth?
mutation {account {login (input: {service:Password params: {email: "[email protected]" password: "supersecretpassword" }}) {tokens {accessToken} } }}

{
"errors": [
{
"message": "Cannot return null for non-nullable field Account.tokens.",
"locations": [
{
"line": 4,
"column": 7
}
],
"path": [
"account",
"login",
"tokens"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"Error: Cannot return null for non-nullable field Account.tokens.",
" at

WHAT WOULD YOU LIKE TO SEE ADDED

As Ultimate Backend becomes stable, please tell me features you would like to see. The constraint is the features most not be project-specific but should be cross-sectional, for instance like messaging, etc. Can't wait to see your feedback :)

Looks interesting

Very much along the lines of what I am looking to do. How mature is this? Any docs? The README seems incomplete...

Scope Request in websocket

I want to use this to build multi-tenant application with web socket that is original to use the Scope. Request for verifying the user in a socket on connection, but how I can get the request for module
async handleConnection(socket: Socket) {

const contextId = ContextIdFactory.getByRequest(???);

  const userService = await this.moduleRef.resolve(
    UsersService,
    contextId,
    { strict: false },
  );

}
My users service

@Injectable({ scope: Scope.REQUEST })
export class UsersService {
}

Again, great library~

service-webhook Dockerfile config typo?

apps/service-webhook/Dockerfile is configured to build service-tenant instead of webhook, it is correct?

# Build production files
RUN nest build proto-schema
RUN nest build service-tenant

# Bundle app source
COPY . .

EXPOSE 50053
CMD ["node", "dist/apps/service-tenant/main.js"]

I am not sure but maybe it is copy-paste typo?
must be:

# Build production files
RUN nest build proto-schema
RUN nest build service-webhook

# Bundle app source
COPY . .

EXPOSE 50053
CMD ["node", "dist/apps/service-webhook/main.js"]

Playground is not defined.

I keep getting this error anytime I run the api-admin.

I've added the playground workspace version but the error is still there.

Documentation

The project has grown quite big in code and would make sense to have the project properly documented. So it can be easily understood in few hours of poking around

Build Error (billing service) : Type is not assignable in billings.controller.ts(134,7)

version : 2.0.0-alpha.2

running npx nest build service-billing gives an error

ERROR in XX/ultimate-backend/apps/service-billing/src/billings/billings.controller.ts
ERROR in XX/ultimate-backend/apps/service-billing/src/billings/billings.controller.ts(134,7):
TS2322: Type 'string | ObjectId' is not assignable to type 'string'.
Type 'ObjectId' is not assignable to type 'string'.

quick fix
(134,7) tenantId: tenant?.id as string

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.