├── .nvmrc ├── .yarnrc ├── apps ├── api │ ├── e2e │ │ ├── mocha.e2e.opts │ │ ├── setup.ts │ │ └── api │ │ │ ├── healthcheck │ │ │ └── health-check.e2e.ts │ │ │ ├── user │ │ │ └── get-me.e2e.ts │ │ │ ├── organization │ │ │ ├── get-my-organization.e2e.ts │ │ │ ├── create-organization.e2e.ts │ │ │ └── members │ │ │ │ ├── get-members.e2e.ts │ │ │ │ └── remove-member.e2e.ts │ │ │ └── auth │ │ │ ├── login.e2e.ts │ │ │ └── user-registration.e2e.ts │ ├── src │ │ ├── app │ │ │ ├── auth │ │ │ │ ├── services │ │ │ │ │ ├── auth.interface.ts │ │ │ │ │ ├── passport │ │ │ │ │ │ ├── jwt.strategy.ts │ │ │ │ │ │ └── github.strategy.ts │ │ │ │ │ └── auth.service.ts │ │ │ │ ├── framework │ │ │ │ │ ├── roles.decorator.ts │ │ │ │ │ ├── gql-auth.guard.ts │ │ │ │ │ └── roles.guard.ts │ │ │ │ ├── usecases │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── login │ │ │ │ │ │ ├── login.command.ts │ │ │ │ │ │ └── login.usecase.ts │ │ │ │ │ ├── switch-organization │ │ │ │ │ │ ├── switch-organization.command.ts │ │ │ │ │ │ └── switch-organization.usecase.ts │ │ │ │ │ └── register │ │ │ │ │ │ ├── user-register.command.ts │ │ │ │ │ │ └── user-register.usecase.ts │ │ │ │ ├── dtos │ │ │ │ │ ├── login.dto.ts │ │ │ │ │ └── user-registration.dto.ts │ │ │ │ ├── auth.module.ts │ │ │ │ └── auth.controller.ts │ │ │ ├── organization │ │ │ │ ├── dtos │ │ │ │ │ ├── get-invite.dto.ts │ │ │ │ │ ├── get-my-organization.dto.ts │ │ │ │ │ ├── invite-member.dto.ts │ │ │ │ │ ├── create-organization.dto.ts │ │ │ │ │ └── bulk-invite-members.dto.ts │ │ │ │ ├── organization.graph.ts │ │ │ │ ├── member.graph.ts │ │ │ │ ├── usecases │ │ │ │ │ ├── membership │ │ │ │ │ │ ├── get-members │ │ │ │ │ │ │ ├── get-members.command.ts │ │ │ │ │ │ │ └── get-members.usecase.ts │ │ │ │ │ │ ├── remove-member │ │ │ │ │ │ │ ├── remove-member.command.ts │ │ │ │ │ │ │ └── remove-member.usecase.ts │ │ │ │ │ │ └── add-member │ │ │ │ │ │ │ ├── add-member.command.ts │ │ │ │ │ │ │ └── add-member.usecase.ts │ │ │ │ │ ├── get-organization │ │ │ │ │ │ ├── get-organization.command.ts │ │ │ │ │ │ └── get-organization.usecase.ts │ │ │ │ │ ├── create-organization │ │ │ │ │ │ ├── create-organization.command.ts │ │ │ │ │ │ └── create-organization.usecase.ts │ │ │ │ │ ├── get-my-organization │ │ │ │ │ │ ├── get-my-organization.command.ts │ │ │ │ │ │ └── get-my-organization.usecase.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── member.resolver.ts │ │ │ │ ├── organization.module.ts │ │ │ │ ├── organization.resolver.ts │ │ │ │ └── organization.controller.ts │ │ │ ├── shared │ │ │ │ ├── constants.ts │ │ │ │ ├── exceptions │ │ │ │ │ └── api.exception.ts │ │ │ │ ├── helpers │ │ │ │ │ ├── regex.service.ts │ │ │ │ │ └── email-normalization.service.ts │ │ │ │ ├── commands │ │ │ │ │ ├── authenticated.command.ts │ │ │ │ │ ├── organization.command.ts │ │ │ │ │ └── command.helper.ts │ │ │ │ ├── framework │ │ │ │ │ ├── user.decorator.ts │ │ │ │ │ └── response.interceptor.ts │ │ │ │ ├── shared.module.ts │ │ │ │ └── crud │ │ │ │ │ └── mongoose-crud.service.ts │ │ │ ├── testing │ │ │ │ ├── usecases │ │ │ │ │ ├── index.ts │ │ │ │ │ └── seed-data │ │ │ │ │ │ ├── seed-data.command.ts │ │ │ │ │ │ └── seed-data.usecase.ts │ │ │ │ ├── dtos │ │ │ │ │ └── seed-data.dto.ts │ │ │ │ ├── testing.module.ts │ │ │ │ └── testing.controller.ts │ │ │ ├── user │ │ │ │ ├── usecases │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── get-my-profile │ │ │ │ │ │ ├── get-my-profile.dto.ts │ │ │ │ │ │ └── get-my-profile.usecase.ts │ │ │ │ │ └── create-user │ │ │ │ │ │ ├── create-user.dto.ts │ │ │ │ │ │ └── create-user.usecase.ts │ │ │ │ ├── user.module.ts │ │ │ │ ├── user.graph.ts │ │ │ │ └── user.resolver.ts │ │ │ ├── health │ │ │ │ ├── health.module.ts │ │ │ │ └── health.controller.ts │ │ │ └── admin │ │ │ │ ├── admin.module.ts │ │ │ │ └── entities │ │ │ │ └── users │ │ │ │ ├── users.service.ts │ │ │ │ └── users.controller.ts │ │ ├── main.ts │ │ ├── schema.graphql │ │ ├── types │ │ │ └── env.d.ts │ │ ├── .graphqlconfig │ │ ├── .example.env │ │ ├── config │ │ │ └── index.ts │ │ ├── .env.test │ │ ├── app.module.ts │ │ └── bootstrap.ts │ ├── .eslintrc.js │ ├── tsconfig.spec.json │ ├── nodemon-debug.json │ ├── nodemon.json │ ├── tsconfig.json │ ├── tsconfig.build.json │ ├── schema.graphql │ ├── .gitignore │ ├── README.md │ └── package.json ├── admin │ ├── src │ │ ├── react-admin.d.ts │ │ ├── react-app-env.d.ts │ │ ├── setupTests.ts │ │ ├── index.css │ │ ├── containers │ │ │ └── users │ │ │ │ └── index.tsx │ │ ├── authProvider.ts │ │ ├── index.tsx │ │ ├── logo.svg │ │ └── serviceWorker.ts │ ├── public │ │ ├── robots.txt │ │ ├── favicon.ico │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── index.html │ ├── .gitignore │ ├── tsconfig.json │ ├── package.json │ └── README.md ├── web │ ├── next-env.d.ts │ ├── public │ │ ├── favicon.ico │ │ └── vercel.svg │ ├── pages │ │ ├── api │ │ │ └── hello.js │ │ └── index.jsx │ ├── .eslintrc.js │ ├── .gitignore │ ├── tsconfig.json │ ├── package.json │ └── README.md └── landing │ └── index.html ├── .dockerignore ├── libs ├── core │ ├── .dockerignore │ ├── src │ │ ├── services │ │ │ ├── queue │ │ │ │ ├── index.ts │ │ │ │ ├── queue.interface.ts │ │ │ │ └── queue.service.ts │ │ │ ├── helper │ │ │ │ └── helper.service.ts │ │ │ ├── cron │ │ │ │ └── cron.service.ts │ │ │ ├── mail │ │ │ │ └── mail.service.ts │ │ │ ├── analytics │ │ │ │ └── analytics.service.ts │ │ │ └── storage │ │ │ │ └── storage.service.ts │ │ ├── dal │ │ │ ├── repositories │ │ │ │ ├── user │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── user.entity.ts │ │ │ │ │ ├── user.repository.ts │ │ │ │ │ └── user.schema.ts │ │ │ │ ├── organization │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── organization.entity.ts │ │ │ │ │ ├── organization.schema.ts │ │ │ │ │ └── organization.repository.ts │ │ │ │ ├── schema-default.options.ts │ │ │ │ └── base-repository.ts │ │ │ ├── index.ts │ │ │ └── dal.service.ts │ │ ├── types │ │ │ └── env.d.ts │ │ ├── index.ts │ │ └── testing │ │ │ ├── test-server.service.ts │ │ │ ├── organization.service.ts │ │ │ └── user.session.ts │ ├── .eslintrc.js │ ├── tsconfig.json │ ├── nodemon.json │ ├── tsconfig.build.json │ ├── package.json │ └── .gitignore └── shared │ ├── .dockerignore │ ├── src │ ├── dto │ │ ├── shared │ │ │ ├── index.ts │ │ │ └── shared.ts │ │ ├── index.ts │ │ └── organization │ │ │ ├── index.ts │ │ │ ├── members │ │ │ ├── bulk-invite-members.dto.ts │ │ │ └── get-invite.dto.ts │ │ │ └── create-organization.dto.ts │ ├── entities │ │ ├── user │ │ │ ├── index.ts │ │ │ ├── user.enums.ts │ │ │ └── user.interface.ts │ │ └── organization │ │ │ ├── member.enum.ts │ │ │ ├── index.ts │ │ │ ├── member.interface.ts │ │ │ └── organization.interface.ts │ └── index.ts │ ├── .eslintrc.js │ ├── tsconfig.json │ ├── nodemon.json │ ├── tsconfig.build.json │ ├── package.json │ └── .gitignore ├── .gitattributes ├── .prettierignore ├── .idea ├── misc.xml ├── vcs.xml ├── dictionaries │ └── dmitrigrossman.xml ├── jsLinters │ └── eslint.xml ├── inspectionProfiles │ └── Project_Default.xml ├── modules.xml ├── runConfigurations │ ├── RUN_PROJECT.xml │ ├── API.xml │ ├── CORE.xml │ ├── SHARED.xml │ ├── _template__of_mocha_javascript_test_runner.xml │ └── API_E2E.xml └── nestjs-monorepo-starter.iml ├── .prettierrc ├── .editorconfig ├── tsconfig.json ├── lerna.json ├── .eslintignore ├── tsconfig.base.json ├── Dockerfile.api ├── .github └── workflows │ └── blank.yml ├── .eslintrc.js ├── package.json ├── .gitignore └── README.md /.nvmrc: -------------------------------------------------------------------------------- 1 | v14.2.0 2 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | network-timeout 60000 -------------------------------------------------------------------------------- /apps/api/e2e/mocha.e2e.opts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | packages/**/node_modules 2 | -------------------------------------------------------------------------------- /libs/core/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /libs/shared/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /apps/api/src/app/auth/services/auth.interface.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/api/src/app/organization/dtos/get-invite.dto.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/admin/src/react-admin.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'react-admin'; 2 | -------------------------------------------------------------------------------- /libs/shared/src/dto/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './shared'; 2 | -------------------------------------------------------------------------------- /apps/admin/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /libs/core/src/services/queue/index.ts: -------------------------------------------------------------------------------- 1 | export * from './queue.service'; 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /apps/api/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrap } from './bootstrap'; 2 | 3 | bootstrap(); 4 | -------------------------------------------------------------------------------- /libs/core/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | }; 4 | -------------------------------------------------------------------------------- /libs/shared/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | }; 4 | -------------------------------------------------------------------------------- /libs/shared/src/dto/index.ts: -------------------------------------------------------------------------------- 1 | export * from './shared'; 2 | export * from './organization'; 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | -------------------------------------------------------------------------------- /apps/admin/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /apps/api/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | rules: {}, 4 | }; 5 | -------------------------------------------------------------------------------- /apps/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | // / 2 | // / 3 | -------------------------------------------------------------------------------- /libs/shared/src/entities/user/index.ts: -------------------------------------------------------------------------------- 1 | export * from './user.enums'; 2 | export * from './user.interface'; 3 | -------------------------------------------------------------------------------- /libs/core/src/dal/repositories/user/index.ts: -------------------------------------------------------------------------------- 1 | export * from './user.repository'; 2 | export * from './user.entity'; 3 | -------------------------------------------------------------------------------- /libs/core/src/services/queue/queue.interface.ts: -------------------------------------------------------------------------------- 1 | export interface IDemoQueuePayload { 2 | userId: string; 3 | } 4 | -------------------------------------------------------------------------------- /apps/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scopsy/nestjs-monorepo-starter/HEAD/apps/web/public/favicon.ico -------------------------------------------------------------------------------- /apps/admin/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scopsy/nestjs-monorepo-starter/HEAD/apps/admin/public/favicon.ico -------------------------------------------------------------------------------- /apps/admin/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scopsy/nestjs-monorepo-starter/HEAD/apps/admin/public/logo192.png -------------------------------------------------------------------------------- /apps/admin/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scopsy/nestjs-monorepo-starter/HEAD/apps/admin/public/logo512.png -------------------------------------------------------------------------------- /apps/api/src/app/shared/constants.ts: -------------------------------------------------------------------------------- 1 | export const QUEUE_SERVICE = 'QueueService'; 2 | export const DAL_SERVICE = 'DalService'; 3 | -------------------------------------------------------------------------------- /libs/shared/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dto'; 2 | export * from './entities/user'; 3 | export * from './entities/organization'; 4 | -------------------------------------------------------------------------------- /libs/core/src/dal/repositories/organization/index.ts: -------------------------------------------------------------------------------- 1 | export * from './organization.repository'; 2 | export * from './organization.entity'; 3 | -------------------------------------------------------------------------------- /libs/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "types": ["node"] 5 | } 6 | } 7 | 8 | -------------------------------------------------------------------------------- /libs/shared/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "types": ["node"] 5 | } 6 | } 7 | 8 | -------------------------------------------------------------------------------- /apps/api/src/app/testing/usecases/index.ts: -------------------------------------------------------------------------------- 1 | import { SeedData } from './seed-data/seed-data.usecase'; 2 | 3 | export const USE_CASES = [SeedData]; 4 | -------------------------------------------------------------------------------- /apps/api/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "apps/api/tsconfig.json", 3 | "compilerOptions": { 4 | "types": ["mocha", "node"] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /libs/shared/src/entities/organization/member.enum.ts: -------------------------------------------------------------------------------- 1 | export enum MemberRoleEnum { 2 | ADMIN = 'admin', 3 | MEMBER = 'member', 4 | BUNNY = 'bunny', 5 | } 6 | -------------------------------------------------------------------------------- /libs/shared/src/entities/organization/index.ts: -------------------------------------------------------------------------------- 1 | export * from './member.enum'; 2 | export * from './member.interface'; 3 | export * from './organization.interface'; 4 | -------------------------------------------------------------------------------- /libs/core/src/dal/repositories/schema-default.options.ts: -------------------------------------------------------------------------------- 1 | export const schemaOptions = { 2 | timestamps: true, 3 | toJSON: { 4 | virtuals: true, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /apps/api/src/app/shared/exceptions/api.exception.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestException } from '@nestjs/common'; 2 | 3 | export class ApiException extends BadRequestException {} 4 | -------------------------------------------------------------------------------- /libs/shared/src/dto/shared/shared.ts: -------------------------------------------------------------------------------- 1 | export interface ISuccessResponseDto { 2 | success: boolean; 3 | } 4 | 5 | export interface IServerResponse { 6 | data: T; 7 | } 8 | -------------------------------------------------------------------------------- /apps/api/src/app/auth/framework/roles.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | 3 | export const Roles = (...roles: string[]) => SetMetadata('roles', roles); 4 | -------------------------------------------------------------------------------- /libs/core/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src"], 3 | "ext": "ts", 4 | "ignore": ["src/**/*.spec.ts"], 5 | "exec": "ts-node -r tsconfig-paths/register src/main.app.ts" 6 | } 7 | -------------------------------------------------------------------------------- /apps/api/src/app/organization/dtos/get-my-organization.dto.ts: -------------------------------------------------------------------------------- 1 | import { OrganizationEntity } from '@nest-starter/core'; 2 | 3 | export type IGetMyOrganizationDto = OrganizationEntity; 4 | -------------------------------------------------------------------------------- /libs/shared/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src"], 3 | "ext": "ts", 4 | "ignore": ["src/**/*.spec.ts"], 5 | "exec": "ts-node -r tsconfig-paths/register src/main.app.ts" 6 | } 7 | -------------------------------------------------------------------------------- /libs/shared/src/dto/organization/index.ts: -------------------------------------------------------------------------------- 1 | export * from './create-organization.dto'; 2 | export * from './members/bulk-invite-members.dto'; 3 | export * from './members/get-invite.dto'; 4 | -------------------------------------------------------------------------------- /libs/shared/src/entities/user/user.enums.ts: -------------------------------------------------------------------------------- 1 | export enum AuthProviderEnum { 2 | GOOGLE = 'google', 3 | GITHUB = 'github', 4 | } 5 | 6 | export enum UserRoleEnum { 7 | USER = 'user', 8 | } 9 | -------------------------------------------------------------------------------- /libs/core/src/dal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dal.service'; 2 | export * from './repositories/user'; 3 | export * from './repositories/base-repository'; 4 | export * from './repositories/organization'; 5 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /apps/api/src/app/shared/helpers/regex.service.ts: -------------------------------------------------------------------------------- 1 | export function escapeRegExp(text: string): string { 2 | if (!text) return text; 3 | 4 | return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 5 | } 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /libs/core/src/types/env.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace NodeJS { 2 | export interface ProcessEnv { 3 | REDIS_URL: string; 4 | REDIS_ARENA_PORT: string; 5 | NODE_ENV: 'test' | 'prod' | 'dev'; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.idea/dictionaries/dmitrigrossman.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | usecase 5 | 6 | 7 | -------------------------------------------------------------------------------- /apps/api/nodemon-debug.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src"], 3 | "ext": "ts", 4 | "ignore": ["src/**/*.spec.ts"], 5 | "exec": "node --inspect-brk -r ts-node/register -r tsconfig-paths/register src/main.ts" 6 | } 7 | -------------------------------------------------------------------------------- /apps/api/src/app/auth/usecases/index.ts: -------------------------------------------------------------------------------- 1 | import { UserRegister } from './register/user-register.usecase'; 2 | import { Login } from './login/login.usecase'; 3 | 4 | export const USE_CASES = [UserRegister, Login]; 5 | -------------------------------------------------------------------------------- /apps/api/src/app/organization/dtos/invite-member.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsEmail, IsNotEmpty } from 'class-validator'; 2 | 3 | export class InviteMemberDto { 4 | @IsEmail() 5 | @IsNotEmpty() 6 | email: string; 7 | } 8 | -------------------------------------------------------------------------------- /.idea/jsLinters/eslint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /apps/web/pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default (req, res) => { 4 | res.statusCode = 200; 5 | res.json({ name: 'John Doe' }); 6 | }; 7 | -------------------------------------------------------------------------------- /apps/api/src/app/shared/commands/authenticated.command.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty } from 'class-validator'; 2 | 3 | export abstract class AuthenticatedCommand { 4 | @IsNotEmpty() 5 | public readonly userId: string; 6 | } 7 | -------------------------------------------------------------------------------- /apps/landing/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | This is a marketing site 9 | 10 | 11 | -------------------------------------------------------------------------------- /apps/api/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src", "../core/dist"], 3 | "ext": "ts", 4 | "delay": 2, 5 | "ignoreRoot": [".git"], 6 | "ignore": ["src/**/*.spec.ts"], 7 | "exec": "ts-node -r tsconfig-paths/register src/main.ts" 8 | } 9 | -------------------------------------------------------------------------------- /apps/api/src/app/testing/dtos/seed-data.dto.ts: -------------------------------------------------------------------------------- 1 | import { UserEntity } from '@nest-starter/core'; 2 | 3 | export class SeedDataBodyDto {} 4 | 5 | export interface ISeedDataResponseDto { 6 | token: string; 7 | user: UserEntity; 8 | } 9 | -------------------------------------------------------------------------------- /apps/api/src/app/auth/dtos/login.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsDefined, IsEmail } from 'class-validator'; 2 | 3 | export class LoginBodyDto { 4 | @IsDefined() 5 | @IsEmail() 6 | email: string; 7 | 8 | @IsDefined() 9 | password: string; 10 | } 11 | -------------------------------------------------------------------------------- /apps/api/src/app/user/usecases/index.ts: -------------------------------------------------------------------------------- 1 | import { CreateUser } from './create-user/create-user.usecase'; 2 | import { GetMyProfileUsecase } from './get-my-profile/get-my-profile.usecase'; 3 | 4 | export const USE_CASES = [CreateUser, GetMyProfileUsecase]; 5 | -------------------------------------------------------------------------------- /apps/web/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['../../.eslintrc.js'], 3 | rules: { 4 | 'react/react-in-jsx-scope': 'off', 5 | 'react/jsx-closing-bracket-location': 'off', 6 | }, 7 | globals: { 8 | React: 'writable', 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /apps/api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "types": [ 5 | "node", 6 | "mocha", 7 | "chai", 8 | "sinon" 9 | ], 10 | "target": "es2016", 11 | "allowJs": false 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /libs/shared/src/dto/organization/members/bulk-invite-members.dto.ts: -------------------------------------------------------------------------------- 1 | export interface IBulkInviteRequestDto { 2 | invitees: { 3 | email: string; 4 | }[]; 5 | } 6 | 7 | export interface IBulkInviteResponse { 8 | success: boolean; 9 | email: string; 10 | } 11 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "trailingComma": "es5", 4 | "singleQuote": true, 5 | "semi": true, 6 | "tabWidth": 2, 7 | "quoteProps": "as-needed", 8 | "jsxSingleQuote": false, 9 | "jsxBracketSameLine": true, 10 | "arrowParens": "always" 11 | } 12 | -------------------------------------------------------------------------------- /apps/api/src/app/organization/organization.graph.ts: -------------------------------------------------------------------------------- 1 | import { Field, ID, ObjectType } from '@nestjs/graphql'; 2 | 3 | @ObjectType() 4 | export class Organization { 5 | @Field((type) => ID) 6 | _id: string; 7 | 8 | @Field({ nullable: true }) 9 | name?: string; 10 | } 11 | -------------------------------------------------------------------------------- /apps/admin/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /apps/api/src/app/testing/usecases/seed-data/seed-data.command.ts: -------------------------------------------------------------------------------- 1 | import { CommandHelper } from '../../../shared/commands/command.helper'; 2 | 3 | export class SeedDataCommand { 4 | static create(data: SeedDataCommand) { 5 | return CommandHelper.create(SeedDataCommand, data); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_style = space 11 | indent_size = 2 12 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "moduleResolution": "node", 5 | "baseUrl": ".", 6 | "paths": { 7 | } 8 | }, 9 | "types": [ 10 | "node", 11 | "mocha", 12 | "chai", 13 | "sinon", 14 | "cypress" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /apps/api/src/app/shared/commands/organization.command.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty } from 'class-validator'; 2 | import { AuthenticatedCommand } from './authenticated.command'; 3 | 4 | export abstract class OrganizationCommand extends AuthenticatedCommand { 5 | @IsNotEmpty() 6 | readonly organizationId: string; 7 | } 8 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "packages": [ 4 | "apps/*", 5 | "libs/*" 6 | ], 7 | "useWorkspaces": true, 8 | "version": "1.2.5", 9 | "command": { 10 | "version": { 11 | "allowBranch": "master", 12 | "message": "chore(release): publish %s" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /libs/shared/src/dto/organization/create-organization.dto.ts: -------------------------------------------------------------------------------- 1 | export interface ICreateOrganizationDto { 2 | name: string; 3 | logo?: string; 4 | taxIdentifier?: string; 5 | } 6 | 7 | export interface IOrganizationDTO { 8 | _id: string; 9 | name: string; 10 | createdAt: Date; 11 | updatedAt: Date; 12 | } 13 | -------------------------------------------------------------------------------- /apps/api/src/app/testing/testing.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { USE_CASES } from './usecases'; 3 | import { TestingController } from './testing.controller'; 4 | 5 | @Module({ 6 | providers: [...USE_CASES], 7 | controllers: [TestingController], 8 | }) 9 | export class TestingModule {} 10 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /apps/api/src/schema.graphql: -------------------------------------------------------------------------------- 1 | # This file was generated based on ".graphqlconfig". Do not edit manually. 2 | 3 | schema { 4 | query: Query 5 | } 6 | 7 | type Query { 8 | me: User! 9 | } 10 | 11 | type User { 12 | _id: ID! 13 | email: String 14 | firstName: String 15 | lastName: String 16 | profilePicture: String 17 | } 18 | -------------------------------------------------------------------------------- /libs/shared/src/dto/organization/members/get-invite.dto.ts: -------------------------------------------------------------------------------- 1 | export interface IGetInviteResponseDto { 2 | inviter: { 3 | _id: string; 4 | firstName: string; 5 | lastName: string; 6 | profilePicture: string; 7 | }; 8 | organization: { 9 | _id: string; 10 | logo: string; 11 | name: string; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 2 | .grunt 3 | 4 | # node-waf configuration 5 | .lock-wscript 6 | 7 | # Dependency directory 8 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 9 | node_modules 10 | 11 | # OSX 12 | .DS_Store 13 | -------------------------------------------------------------------------------- /libs/core/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "target": "es6", 6 | "declaration": true, 7 | "outDir": "./dist", 8 | "rootDir": "./src", 9 | "types": ["node"] 10 | }, 11 | "include": [ 12 | "src/**/*" 13 | ] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /libs/shared/src/entities/organization/member.interface.ts: -------------------------------------------------------------------------------- 1 | export enum MemberStatusEnum { 2 | NEW = 'new', 3 | ACTIVE = 'active', 4 | INVITED = 'invited' 5 | } 6 | 7 | export interface IMemberInvite { 8 | email: string; 9 | token: string; 10 | invitationDate: Date; 11 | answerDate?: Date; 12 | _inviterId: string; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /libs/shared/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "target": "es6", 6 | "declaration": true, 7 | "outDir": "./dist", 8 | "rootDir": "./src", 9 | "types": ["node"] 10 | }, 11 | "include": [ 12 | "src/**/*" 13 | ] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /apps/api/src/app/organization/member.graph.ts: -------------------------------------------------------------------------------- 1 | import { Field, ID, ObjectType } from '@nestjs/graphql'; 2 | import { MemberStatusEnum } from '@nest-starter/shared'; 3 | 4 | @ObjectType() 5 | export class Member { 6 | @Field((type) => ID) 7 | _id: string; 8 | 9 | @Field() 10 | _userId: string; 11 | 12 | @Field() 13 | memberStatus: MemberStatusEnum; 14 | } 15 | -------------------------------------------------------------------------------- /apps/api/src/types/env.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace NodeJS { 2 | export interface ProcessEnv { 3 | MONGO_URL: string; 4 | REDIS_URL: string; 5 | SYNC_PATH: string; 6 | GOOGLE_OAUTH_CLIENT_SECRET: string; 7 | GOOGLE_OAUTH_CLIENT_ID: string; 8 | NODE_ENV: 'test' | 'prod' | 'dev' | 'ci'; 9 | PORT: string; 10 | FRONT_BASE_URL: string; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.idea/runConfigurations/RUN_PROJECT.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /apps/api/src/.graphqlconfig: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Untitled GraphQL Schema", 3 | "schemaPath": "schema.graphql", 4 | "extensions": { 5 | "endpoints": { 6 | "Default GraphQL Endpoint": { 7 | "url": "http://localhost:3000/graphql", 8 | "headers": { 9 | "user-agent": "JS GraphQL" 10 | }, 11 | "introspect": false 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apps/api/src/app/auth/dtos/user-registration.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsDefined, IsEmail, IsNotEmpty, MinLength } from 'class-validator'; 2 | 3 | export class UserRegistrationBodyDto { 4 | @IsDefined() 5 | @IsEmail() 6 | email: string; 7 | 8 | @IsDefined() 9 | @MinLength(8) 10 | password: string; 11 | 12 | @IsDefined() 13 | firstName: string; 14 | 15 | @IsDefined() 16 | lastName: string; 17 | } 18 | -------------------------------------------------------------------------------- /apps/api/src/app/health/health.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TerminusModule } from '@nestjs/terminus'; 3 | import { SharedModule } from '../shared/shared.module'; 4 | import { HealthController } from './health.controller'; 5 | 6 | @Module({ 7 | imports: [SharedModule, TerminusModule], 8 | controllers: [HealthController], 9 | providers: [], 10 | }) 11 | export class HealthModule {} 12 | -------------------------------------------------------------------------------- /apps/api/src/app/user/usecases/get-my-profile/get-my-profile.dto.ts: -------------------------------------------------------------------------------- 1 | import { AuthenticatedCommand } from '../../../shared/commands/authenticated.command'; 2 | import { CommandHelper } from '../../../shared/commands/command.helper'; 3 | 4 | export class GetMyProfileCommand extends AuthenticatedCommand { 5 | static create(data: GetMyProfileCommand) { 6 | return CommandHelper.create(GetMyProfileCommand, data); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /apps/admin/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /libs/shared/src/entities/user/user.interface.ts: -------------------------------------------------------------------------------- 1 | export interface IUserEntity { 2 | _id: string; 3 | firstName: string; 4 | lastName: string; 5 | email: string; 6 | profilePicture: string; 7 | createdAt: string; 8 | } 9 | 10 | export interface IJwtPayload { 11 | _id: string; 12 | firstName: string; 13 | lastName: string; 14 | email: string; 15 | profilePicture: string; 16 | organizationId?: string; 17 | } 18 | -------------------------------------------------------------------------------- /apps/api/src/app/organization/usecases/membership/get-members/get-members.command.ts: -------------------------------------------------------------------------------- 1 | import { CommandHelper } from '../../../../shared/commands/command.helper'; 2 | import { OrganizationCommand } from '../../../../shared/commands/organization.command'; 3 | 4 | export class GetMembersCommand extends OrganizationCommand { 5 | static create(data: GetMembersCommand) { 6 | return CommandHelper.create(GetMembersCommand, data); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /apps/api/src/app/user/user.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { SharedModule } from '../shared/shared.module'; 3 | import { USE_CASES } from './usecases'; 4 | import { UserResolver } from './user.resolver'; 5 | 6 | @Module({ 7 | imports: [SharedModule], 8 | controllers: [], 9 | providers: [...USE_CASES, UserResolver], 10 | exports: [...USE_CASES, UserResolver], 11 | }) 12 | export class UserModule {} 13 | -------------------------------------------------------------------------------- /apps/admin/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /apps/api/src/app/admin/admin.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { SharedModule } from '../shared/shared.module'; 3 | import { UsersController } from './entities/users/users.controller'; 4 | import { UsersService } from './entities/users/users.service'; 5 | 6 | @Module({ 7 | imports: [SharedModule], 8 | controllers: [UsersController], 9 | providers: [UsersService], 10 | }) 11 | export class AdminModule {} 12 | -------------------------------------------------------------------------------- /libs/core/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dal'; 2 | export * from './services/queue'; 3 | export * from './services/helper/helper.service'; 4 | export * from './services/cron/cron.service'; 5 | export * from './testing/test-server.service'; 6 | export * from './testing/user.session'; 7 | export * from './services/storage/storage.service'; 8 | export * from './services/analytics/analytics.service'; 9 | export * from './services/mail/mail.service'; 10 | -------------------------------------------------------------------------------- /libs/core/src/testing/test-server.service.ts: -------------------------------------------------------------------------------- 1 | export class TestServer { 2 | private app; 3 | 4 | getHttpServer() { 5 | return this.app.getHttpServer(); 6 | } 7 | 8 | getService(service) { 9 | return this.app.get(service); 10 | } 11 | 12 | async create(app) { 13 | this.app = app; 14 | } 15 | 16 | async teardown() { 17 | await this.app.close(); 18 | } 19 | } 20 | 21 | export const testServer = new TestServer(); 22 | -------------------------------------------------------------------------------- /.idea/runConfigurations/API.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |