Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(backend): migrate to nestjs #68

Merged
merged 10 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,17 +132,6 @@ jobs:
echo "No Embed Release"
fi

- name: Trigger Lambda Release
continue-on-error: true
run: |
LAMBDA_VERSION=$(jq -r '.releases[] | select(.name == "@snipcode/code-embed") | .newVersion' release.json)
if [ -n "$LAMBDA_VERSION" ]; then
echo "Ready to release Lambda version $LAMBDA_VERSION"
gh workflow run deploy-lambda.yml -r "${{ secrets.GH_BRANCH }}" -f version=$LAMBDA_VERSION
else
echo "No Lambda Release"
fi

- name: Delete Release File
if: ${{ success() }}
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
- name: Run tests
run: |
yarn prisma migrate dev --schema=packages/domain/prisma/schema.prisma
yarn test
yarn test -- --runInBand --coverage

preview-frontend:
runs-on: ubuntu-latest
Expand Down
52 changes: 0 additions & 52 deletions .github/workflows/deploy-lambda.yml

This file was deleted.

8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ Snipcode is an open-source code-sharing platform that makes it easy to create co

## Tech Stack
* [Node.js](https://nodejs.org/en/)
* [Typescript](https://www.typescriptlang.org/)
* [TypeScript](https://www.typescriptlang.org/)
* [GraphQL](https://graphql.org/)
* [MySQL 8 through PlanetScale](https://planetscale.com/)
* [MySQL 8 with PlanetScale](https://planetscale.com/)
* [Prisma](https://www.prisma.io/)
* [Tailwind CSS](https://tailwindcss.com/)
* [AWS](https://aws.amazon.com)
Expand All @@ -26,9 +26,7 @@ Snipcode is an open-source code-sharing platform that makes it easy to create co
```text
snipcode
├─ apps
│ ├─ core
│ ├─ functions
│ │ ├─ code-embed
│ ├─ backend
│ ├─ web
├─ packages
│ ├─ database
Expand Down
File renamed without changes.
7 changes: 4 additions & 3 deletions apps/core/.env.example → apps/backend/.env.example
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
NODE_ENV=development
APP_VERSION=1.0.0
HOST=http:https://localhost
PORT=7501
ENABLE_INTROSPECTION=true
INTROSPECTION_ENABLED=true
DATABASE_URL="mysql:https://root:@127.0.0.1:3311/snipcode"
ADMIN_PASSWORD=nwHSvXuQxjey43Bp
CONVERTKIT_API_KEY=convertKitApiKey
CONVERTKIT_FORM_ID=formId
CONVERTKIT_TAG_ID=tagId
REQUEST_TIMEOUT=30000
GITHUB_CLIENT_ID=<github_client_id_here>
GITHUB_CLIENT_SECRET=<github_client_secret_here>
WEB_APP_URL=http:https://localhost:7500
Expand All @@ -16,4 +16,5 @@ WEB_AUTH_ERROR_URL=http:https://localhost:7500/auth/error
SESSION_LIFETIME=90# 90 days
SENTRY_DSN=
SENTRY_ENABLED=false
SNIPPET_RENDERER_URL=http:https://localhost:3000/dev
SNIPPET_RENDERER_API_URL=http:https://localhost:3000/dev
JWT_SECRET=jwtSecret
20 changes: 20 additions & 0 deletions apps/backend/.env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
NODE_ENV=test
APP_VERSION=1.1.0
HOST=http:https://localhost
PORT=7509
INTROSPECTION_ENABLED=false
DATABASE_URL="mysql:https://root:[email protected]:3313/snipcode"
ADMIN_PASSWORD=qwerty
CONVERTKIT_API_KEY=convertkit-api-key
CONVERTKIT_FORM_ID=convertkit-form-id
CONVERTKIT_TAG_ID=convertkit-tag-id
GITHUB_CLIENT_ID=github-client-id
GITHUB_CLIENT_SECRET=github-client-secret
WEB_APP_URL=http:https://localhost:7500
WEB_AUTH_SUCCESS_URL=http:https://localhost:7500/auth/success
WEB_AUTH_ERROR_URL=http:https://localhost:7500/auth/error
SESSION_LIFETIME=90
SENTRY_DSN=sentry-dsn
SENTRY_ENABLED=false
SNIPPET_RENDERER_API_URL=http:https://localhost:3000/dev
JWT_SECRET=jwtSecret
11 changes: 11 additions & 0 deletions apps/backend/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
root: true,
extends: '../../.eslintrc.json',
ignorePatterns: ['jest.config.ts', '.eslintrc.js', 'graphql.schema.ts', 'generated.ts'],
parserOptions: {
ecmaVersion: 2023,
sourceType: 'module',
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
},
};
57 changes: 57 additions & 0 deletions apps/backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# compiled output
/dist
/node_modules
/build

# 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

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
.env.docker

# temp directory
.temp
.tmp

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
2 changes: 1 addition & 1 deletion apps/core/CHANGELOG.md → apps/backend/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# @snipcode/core
# @snipcode/backend

## 1.1.0

Expand Down
8 changes: 4 additions & 4 deletions apps/core/Dockerfile → apps/backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ RUN yarn install

RUN npx prisma generate --schema=./packages/domain/prisma/schema.prisma

RUN yarn build --filter=...@snipcode/core
RUN yarn build --filter=...@snipcode/backend


FROM node:20-alpine as schema-builder
Expand Down Expand Up @@ -40,8 +40,8 @@ RUN corepack enable && yarn set version berry
COPY --chown=node:node --from=builder /app/package.json .
COPY --chown=node:node --from=builder /app/.yarnrc.yml .

COPY --chown=node:node --from=builder /app/apps/core/dist/src ./apps/core/src
COPY --chown=node:node --from=builder /app/apps/core/package.json ./apps/core
COPY --chown=node:node --from=builder /app/apps/backend/dist/src ./apps/backend/src
COPY --chown=node:node --from=builder /app/apps/backend/package.json ./apps/backend

COPY --chown=node:node --from=builder /app/packages/domain/package.json ./packages/domain/package.json
COPY --chown=node:node --from=builder /app/packages/domain/dist ./packages/domain/dist
Expand All @@ -61,4 +61,4 @@ COPY --chown=node:node --from=schema-builder /app/node_modules/.prisma/client .

EXPOSE 7501

CMD ["node", "apps/core/src/index.js"]
CMD ["node", "apps/backend/src/main.js"]
95 changes: 95 additions & 0 deletions apps/backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Snipcode Core

This is the backend of Snipcode, containing the business logics related to .

## Tech Stack
* Node.js
* TypeScript
* GraphQL
* MySQL
* Prisma

## Prerequisites
Make sure you have this tools installed before running the project
* Node.js 20+
* NPM or Yarn
* Docker
* AWS CLI v2
* MySQL 8 on PlanetScale

## Packages dependencies
We use Yarn workspace to create packages we can share with other applications.
These packages are located in the folder `packages`, so you might need to change the code of one or many packages to implement a feature.
Here are the packages used in this project:

* [@snipcode/domain](../../packages/domain)
* [@snipcode/embed](../../packages/embed)
* [@snipcode/utils](../../packages/utils)

## Set up the project
Delete the existing folders output from build commands
```shell
yarn clean
```
Install node modules
````shell
yarn install
````
Create configuration file from the template
```shell
cp .env.template .env.local

# Edit configuration to match your local environment and save
nano .env.local
```

**Environment variables list**

| Variable | Description |
|--------------------------|--------------------------------------------------------------------------------------|
| NODE_ENV | Node.js environment (default: development) |
| APP_VERSION | The current version of the application |
| HOST | Host name where the application is running (default: http:https://localhost) |
| PORT | Port number of the application (default: 7501) |
| ENABLE_INTROSPECTION | Enable/Disable GraphQL introspection (must `false` in production) |
| DATABASE_URL | URL of the database |
| ADMIN_PASSWORD | Password of the default admin user. |
| CONVERTKIT_API_KEY | ConvertKit API key |
| CONVERTKIT_FORM_ID | ConvertKit Form ID |
| CONVERTKIT_TAG_ID | ConvertKit Tag ID |
| REQUEST_TIMEOUT | Max duration of a request (default: 30 seconds) |
| GITHUB_CLIENT_ID | GitHub application client ID for authentication with GitHub |
| GITHUB_CLIENT_SECRET | GitHub application client secret for authentication with GitHub |
| WEB_APP_URL | URL of the frontend the application that communicates with this app |
| WEB_AUTH_SUCCESS_URL | Callback URL of the frontend application when the authentication succeed |
| WEB_AUTH_ERROR_URL | Callback URL of the frontend application when the authentication failed |
| SESSION_LIFETIME | The session's lifetime when a user authenticate (default: 90 days) |
| SENTRY_DSN | Sentry DSN |
| SENTRY_ENABLED | Enable/Disable Sentry |
| SNIPPET_RENDERER_API_URL | Base URL of the API (the current one) for generating the html content from a snippet |
| JWT_SECRET | The secret code for decoding JWT token generated in the application |

Start the application
```bash
yarn dev
```
The application will be launched by [Nodemon](https://nodemon.com).

Open [http:https://localhost:7501/graphql](http:https://localhost:7501/graphql) in your browser and use Apollo studio explorer to test your GraphQL queries and mutations.

## Running tests
Run the command below to run all the tests
```shell
yarn test
```
To run a specific test file, append the filename after the command
```shell
yarn test controller.test.ts
```

## Lint the project
ESLint and Prettier are used to normalize the code style across the project.
Linting the code make sure there is no error
```shell
yarn lint
```
File renamed without changes.
5 changes: 4 additions & 1 deletion apps/core/env.d.ts → apps/backend/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ export type EnvironmentVariables = {
CONVERTKIT_FORM_ID: string;
CONVERTKIT_TAG_ID: string;
DATABASE_URL: string;
ENABLE_INTROSPECTION: string;
GITHUB_CLIENT_ID: string;
GITHUB_CLIENT_SECRET: string;
HOST: string;
INTROSPECTION_ENABLED: string;
JWT_SECRET: string;
NODE_ENV: string;
PORT: string;
REQUEST_TIMEOUT: string;
SENTRY_DSN: string;
SENTRY_ENABLED: string;
SESSION_LIFETIME: string;
SNIPPET_RENDERER_URL: string;
WEB_APP_URL: string;
Expand Down
15 changes: 9 additions & 6 deletions apps/core/jest.config.ts → apps/backend/jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import type { Config } from '@jest/types';

const config: Config.InitialOptions = {
roots: ['.'],
preset: 'ts-jest',
testMatch: ['**/?(*.)+(spec|test).[jt]s'],
testEnvironment: 'node',
clearMocks: true,
maxWorkers: 1,
moduleFileExtensions: ['js', 'json', 'ts'],
preset: 'ts-jest',
roots: ['.'],
snapshotFormat: {
"printBasicPrototype": false
}
printBasicPrototype: false,
},
testEnvironment: 'node',
testMatch: ['**/?(*.)+(spec|test).[jt]s'],
collectCoverageFrom: ['**/*.(t|j)s'],
coverageDirectory: '../coverage',
};

export default config;
8 changes: 8 additions & 0 deletions apps/backend/nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
}
}
Loading