Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
JohannThapa committed Oct 26, 2024
1 parent b83537c commit dbd0871
Show file tree
Hide file tree
Showing 257 changed files with 29,335 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/node_modules
/.data
/dist
/files
94 changes: 94 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Application Configuration

NODE_ENV=development # (e.g., development, staging, production)
APP_PORT=application-port
APP_NAME=application-name
API_PREFIX=prefix-for-API-endpoints # (e.g., "/api/users")
APP_FALLBACK_LANGUAGE=en # Default language("en")
APP_HEADER_LANGUAGE=custom-header-used-for-lang-negotiation # (e.g., "x-custom-lang")

# Domain of the application
FRONTEND_DOMAIN=frontend-domain
BACKEND_DOMAIN=backend-domain

# Database Configuration

DATABASE_TYPE=database-type # (e.g., postgres, mysql)
DATABASE_HOST=database-host # (e.g., localhost or database server IP)
DATABASE_PORT=database-port # (e.g., 5432)
DATABASE_USERNAME=database-username
DATABASE_PASSWORD=database-password
DATABASE_NAME=database-name
DATABASE_SYNCHRONIZE=synchronize-database-schema-with-entity-models # (**set to false in production!**)
DATABASE_MAX_CONNECTIONS=maximum-number-of-connections-allowed-to-the-database ## (e.g., 100)
DATABASE_SSL_ENABLED=enable-SSL-encryption-for-database-connections # (**set to true in production!**)
DATABASE_REJECT_UNAUTHORIZED=reject-unauthorized-connections # (recommended true for production)
DATABASE_CA=path-to-CA-certificate # (if using custom CA)
DATABASE_KEY=path-to-client-key # (if using client-side SSL)
DATABASE_CERT=path-to-client-certificate # (if using client-side SSL)
DATABASE_URL=database-connection-URL # (e.g., postgres://user:password@host:port/database)

# NOTE: Optional configuration for database SSL connections
# DATABASE_CA=path/to/ca-certificate.pem (if using custom CA)
# DATABASE_KEY=path/to/client-key.pem (if using client-side SSL)
# DATABASE_CERT=path/to/client-cert.pem (if using client-side SSL)

# Alternatively, use a database connection URL (recommended for security)
# DATABASE_URL=postgres://user:password@host:port/database?sslmode=disable

# Supabase Configuration (Optional)

SUPABASE_URL=supabase-url # Supabase API URL
SUPABASE_KEY=supabase-anon-key # Supabase Anon Key

# File Storage Configuration (choose one driver)
FILE_DRIVER=local # File storage driver (local, s3, s3-presigned)
ACCESS_KEY_ID=access-key-id # AWS S3 access key ID (leave empty for local storage)
SECRET_ACCESS_KEY=secret-access-key # AWS S3 secret access key (leave empty for local storage)
AWS_S3_REGION=aws-region # AWS S3 region
AWS_DEFAULT_S3_BUCKET=s3-bucket-name # Default S3 bucket name

# Email Configuration

MAIL_HOST=mail-server-host
MAIL_PORT=mail-server-port
MAIL_USER=mail-server-username
MAIL_PASSWORD=mail-server-password
# Ignore TLS certificate verification
MAIL_IGNORE_TLS=true # (**not recommended for production!**)
# Use secure (TLS) connections for email (recommended)
MAIL_SECURE=false # Use secure (TLS) connections for email
MAIL_REQUIRE_TLS=false # Require TLS encryption for email (recommended)#
MAIL_DEFAULT_EMAIL=noreply@example.com # Default email address for sending emails
MAIL_DEFAULT_NAME=email-sender-name # Default name for the email sender
MAIL_CLIENT_PORT=mail-client-port

# Authentication Configuration

AUTH_JWT_SECRET=jwt-secret # (never store this in version control!)
AUTH_JWT_TOKEN_EXPIRES_IN=expiration-time-for-token # (e.g., 15m)
AUTH_REFRESH_SECRET=refresh-secret # (never store this in version control!)
AUTH_REFRESH_TOKEN_EXPIRES_IN=refresh-token-expiration-time # (e.g., 3650d)
AUTH_FORGOT_SECRET=your_forgot_secret # Secret key for forgot password tokens (never store this in version control!)
AUTH_FORGOT_TOKEN_EXPIRES_IN=forgot-password-token-expiration-time # (e.g., 30m)
AUTH_CONFIRM_EMAIL_SECRET=confirm_email_secret # Secret key for email confirmation tokens (never store this in version control!)
AUTH_CONFIRM_EMAIL_TOKEN_EXPIRES_IN=confirmation-token-expiration-time # (e.g., 1d)

# Social Login Configuration

## Facebook
FACEBOOK_APP_ID=facebook-app-id # (never store this in version control!)
FACEBOOK_APP_SECRET=facebook-app-secret-key #(never store this in version control!)
FACEBOOK_REDIRECT_URI=redirect-URI-for-Facebook-login
# Google
GOOGLE_CLIENT_ID=google-client-id # (never store this in version control!)
GOOGLE_CLIENT_SECRET=google-secret-key # (never store this in version control!)
# Apple App Audience (optional for Apple Sign In)
APPLE_APP_AUDIENCE=[]
# Twitter
TWITTER_CONSUMER_KEY=twitter-consumer-key # (never store this in version control!)
TWITTER_CONSUMER_SECRET=twitter-consumer-secret # (never store this in version control!)

# Queue System Configuration (Optional)

WORKER_HOST=REDIS_CONNECTION_URL_FOR_WORKER_QUEUE # (e.g., redis://redis:<port>/1)
31 changes: 31 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: Shchepotin

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Send '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
- OS: [e.g. Windows]
- NodeJS Version [e.g. 18.16.0]
- Database [e.g. PostgreSQL]

**Additional context**
Add any other context about the problem here.
33 changes: 33 additions & 0 deletions .github/workflows/docker-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: NestJS API CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

# <database-relational-block>
- name: Run e2e tests for NestJS with TypeORM
id: relational
run: docker compose -f docker-compose.relational.ci.yaml --env-file env-example-relational -p ci-relational up --build --exit-code-from api

- name: Copy prod.log from container to host
if: ${{ failure() && steps.relational.conclusion == 'failure' }}
run: docker cp ci-relational-api-1:/usr/src/app/prod.log .
# </database-relational-block>



- name: Upload prod.log to artifacts for debugging
if: failure()
uses: actions/upload-artifact@v4
with:
name: prod-logs
path: prod.log
43 changes: 43 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# compiled output
/dist
/node_modules

# Logs
logs
*.log
npm-debug.log*
pnpm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# OS
.DS_Store

# Tests
/coverage
/.nyc_output

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

.data
/files
.env
/ormconfig.json
env-example-relational
documentation
documentation/*
1 change: 1 addition & 0 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx commitlint --edit
2 changes: 2 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
npm run lint
npm run test -- --passWithNoTests
3 changes: 3 additions & 0 deletions .hygen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
templates: `${__dirname}/.hygen`,
};
6 changes: 6 additions & 0 deletions .hygen/generate/relational-resource/app-module-import.ejs.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
inject: true
to: src/app.module.ts
before: \@Module
---
import { <%= h.inflection.transform(name, ['pluralize']) %>Module } from './<%= h.inflection.transform(name, ['pluralize', 'underscore', 'dasherize']) %>/<%= h.inflection.transform(name, ['pluralize', 'underscore', 'dasherize']) %>.module';
6 changes: 6 additions & 0 deletions .hygen/generate/relational-resource/app-module.ejs.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
inject: true
to: src/app.module.ts
after: imports
---
<%= h.inflection.transform(name, ['pluralize']) %>Module,
114 changes: 114 additions & 0 deletions .hygen/generate/relational-resource/controller.ejs.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
to: src/<%= h.inflection.transform(name, ['pluralize', 'underscore', 'dasherize']) %>/<%= h.inflection.transform(name, ['pluralize', 'underscore', 'dasherize']) %>.controller.ts
---
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
UseGuards,
Query,
} from '@nestjs/common';
import { <%= h.inflection.transform(name, ['pluralize']) %>Service } from './<%= h.inflection.transform(name, ['pluralize', 'underscore', 'dasherize']) %>.service';
import { Create<%= name %>Dto } from './dto/create-<%= h.inflection.transform(name, ['underscore', 'dasherize']) %>.dto';
import { Update<%= name %>Dto } from './dto/update-<%= h.inflection.transform(name, ['underscore', 'dasherize']) %>.dto';
import {
ApiBearerAuth,
ApiCreatedResponse,
ApiOkResponse,
ApiParam,
ApiTags,
} from '@nestjs/swagger';
import { <%= name %> } from './domain/<%= h.inflection.transform(name, ['underscore', 'dasherize']) %>';
import { AuthGuard } from '@nestjs/passport';
import {
InfinityPaginationResponse,
InfinityPaginationResponseDto,
} from '../utils/dto/infinity-pagination-response.dto';
import { infinityPagination } from '../utils/infinity-pagination';
import { FindAll<%= h.inflection.transform(name, ['pluralize']) %>Dto } from './dto/find-all-<%= h.inflection.transform(name, ['pluralize', 'underscore', 'dasherize']) %>.dto';

@ApiTags('<%= h.inflection.transform(name, ['pluralize', 'humanize']) %>')
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'))
@Controller({
path: '<%= h.inflection.transform(name, ['pluralize', 'underscore', 'dasherize']) %>',
version: '1',
})
export class <%= h.inflection.transform(name, ['pluralize']) %>Controller {
constructor(private readonly <%= h.inflection.camelize(h.inflection.pluralize(name), true) %>Service: <%= h.inflection.transform(name, ['pluralize']) %>Service) {}

@Post()
@ApiCreatedResponse({
type: <%= name %>,
})
create(@Body() create<%= name %>Dto: Create<%= name %>Dto) {
return this.<%= h.inflection.camelize(h.inflection.pluralize(name), true) %>Service.create(create<%= name %>Dto);
}

@Get()
@ApiOkResponse({
type: InfinityPaginationResponse(<%= name %>),
})
async findAll(
@Query() query: FindAll<%= h.inflection.transform(name, ['pluralize']) %>Dto,
): Promise<InfinityPaginationResponseDto<<%= name %>>> {
const page = query?.page ?? 1;
let limit = query?.limit ?? 10;
if (limit > 50) {
limit = 50;
}

return infinityPagination(
await this.<%= h.inflection.camelize(h.inflection.pluralize(name), true) %>Service.findAllWithPagination({
paginationOptions: {
page,
limit,
},
}),
{ page, limit },
);
}

@Get(':id')
@ApiParam({
name: 'id',
type: String,
required: true,
})
@ApiOkResponse({
type: <%= name %>,
})
findById(@Param('id') id: string) {
return this.<%= h.inflection.camelize(h.inflection.pluralize(name), true) %>Service.findById(id);
}

@Patch(':id')
@ApiParam({
name: 'id',
type: String,
required: true,
})
@ApiOkResponse({
type: <%= name %>,
})
update(
@Param('id') id: string,
@Body() update<%= name %>Dto: Update<%= name %>Dto,
) {
return this.<%= h.inflection.camelize(h.inflection.pluralize(name), true) %>Service.update(id, update<%= name %>Dto);
}

@Delete(':id')
@ApiParam({
name: 'id',
type: String,
required: true,
})
remove(@Param('id') id: string) {
return this.<%= h.inflection.camelize(h.inflection.pluralize(name), true) %>Service.remove(id);
}
}
17 changes: 17 additions & 0 deletions .hygen/generate/relational-resource/domain/domain.ejs.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
to: src/<%= h.inflection.transform(name, ['pluralize', 'underscore', 'dasherize']) %>/domain/<%= h.inflection.transform(name, ['underscore', 'dasherize']) %>.ts
---
import { ApiProperty } from '@nestjs/swagger';

export class <%= name %> {
@ApiProperty({
type: String,
})
id: string;

@ApiProperty()
createdAt: Date;

@ApiProperty()
updatedAt: Date;
}
6 changes: 6 additions & 0 deletions .hygen/generate/relational-resource/dto/create.dto.ejs.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
to: src/<%= h.inflection.transform(name, ['pluralize', 'underscore', 'dasherize']) %>/dto/create-<%= h.inflection.transform(name, ['underscore', 'dasherize']) %>.dto.ts
---
export class Create<%= name %>Dto {
// Don't forget to use the class-validator decorators in the DTO properties.
}
12 changes: 12 additions & 0 deletions .hygen/generate/relational-resource/dto/domain.dto.ejs.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
to: src/<%= h.inflection.transform(name, ['pluralize', 'underscore', 'dasherize']) %>/dto/<%= h.inflection.transform(name, ['underscore', 'dasherize']) %>.dto.ts
---
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';

export class <%= name %>Dto {
@ApiProperty()
@IsString()
@IsNotEmpty()
id: string;
}
Loading

0 comments on commit dbd0871

Please sign in to comment.