feat: add docker compose, use @fennec/configuration.

This commit is contained in:
Ivan Li 2021-10-31 14:53:11 +08:00
parent ece8ccf27a
commit 4b8bb47800
10 changed files with 599 additions and 469 deletions

View File

@ -1,13 +1,14 @@
{ {
"cSpell.words": [ "cSpell.words": [
"Repos",
"boardcat", "boardcat",
"execa",
"gitea", "gitea",
"lpush", "lpush",
"lrange", "lrange",
"metatype", "metatype",
"pmessage", "pmessage",
"psubscribe", "psubscribe",
"Repos",
"rpop", "rpop",
"rpush" "rpush"
] ]

View File

@ -17,5 +17,3 @@ db:
etcd: etcd:
hosts: hosts:
- 'http://192.168.31.194:2379' - 'http://192.168.31.194:2379'
workspaces:
root: '/Users/ivanli/Projects/fennec/workspaces'

View File

@ -0,0 +1,20 @@
version: "3.9"
services:
postgres:
image: 'postgres:14'
restart: always
environment:
- POSTGRES_HOST_AUTH_METHOD=trust
ports:
- '${PG_PORT}:5432'
redis:
image: 'redis:6'
restart: always
ports:
- '${REDIS_PORT}:6379'
networks:
default:
name: 'blog-dev'
driver: bridge

61
docker/init-dev.mjs Normal file
View File

@ -0,0 +1,61 @@
import execa from 'execa';
import { URL } from 'url';
import { findFreePorts } from 'find-free-ports';
import YAML from 'js-yaml';
import { readFile, writeFile } from 'fs/promises';
const [PG_PORT, REDIS_PORT] = await findFreePorts(2);
await execa(
'docker-compose',
[
'-f',
new URL('./docker-compose.dev.yml', import.meta.url).pathname,
'up',
'-d',
],
{
env: {
PG_PORT,
REDIS_PORT,
},
stdout: process.stdout,
stderr: process.stderr,
},
);
console.log(`✅ Postgres is running on port ${PG_PORT}`);
console.log(`✅ Redis is running on port ${REDIS_PORT}`);
const config = await YAML.load(
await readFile(
new URL('../config.yml.example', import.meta.url).pathname,
'utf-8',
),
);
config.db.postgres = {
host: 'localhost',
port: PG_PORT,
database: 'postgres',
username: 'postgres',
password: '',
};
config.db.redis = {
host: 'localhost',
port: REDIS_PORT,
};
const configOutputPath = new URL('../config.yml', import.meta.url).pathname;
await writeFile(configOutputPath, YAML.dump(config), 'utf-8');
console.log(`✅ Config file is written to ${configOutputPath}`);
await execa.command('npm run typeorm -- migration:run', {
cwd: new URL('../', import.meta.url).pathname,
stdout: process.stdout,
stderr: process.stderr,
});
console.log(`✅ Database Initiated!`);

View File

@ -0,0 +1,20 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class articleAndTagMigration1635661602570 implements MigrationInterface {
name = 'articleAndTagMigration1635661602570'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "article" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP, "title" character varying NOT NULL, "content" text NOT NULL, "publishedAt" TIMESTAMP, "tags" character varying array NOT NULL, CONSTRAINT "PK_40808690eb7b915046558c0f81b" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_f330baf6be412e8dd60ff7f78e" ON "article" ("publishedAt") `);
await queryRunner.query(`CREATE TABLE "tag" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP, "name" character varying(100) NOT NULL, CONSTRAINT "PK_8e4052373c579afc1471f526760" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_6a9775008add570dc3e5a0bab7" ON "tag" ("name") `);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX "public"."IDX_6a9775008add570dc3e5a0bab7"`);
await queryRunner.query(`DROP TABLE "tag"`);
await queryRunner.query(`DROP INDEX "public"."IDX_f330baf6be412e8dd60ff7f78e"`);
await queryRunner.query(`DROP TABLE "article"`);
}
}

22
ormconfig.js Normal file
View File

@ -0,0 +1,22 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const yaml = require('js-yaml');
const fs = require('fs');
const path = require('path');
const config = yaml.load(
fs.readFileSync(path.join(__dirname, './config.yml'), 'utf8'),
);
module.exports = {
type: 'postgres',
host: config.db.postgres.host,
port: config.db.postgres.port,
username: config.db.postgres.username,
password: config.db.postgres.password,
database: config.db.postgres.database,
migrations: ['migrations/**/*.ts'],
entities: ['src/**/*.entity.ts'],
cli: {
migrationsDir: 'migrations',
},
};

919
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,15 +13,17 @@
"start:dev": "DEBUG=fennec:* nest start --watch", "start:dev": "DEBUG=fennec:* nest start --watch",
"start:debug": "DEBUG=fennec:* nest start --debug --watch", "start:debug": "DEBUG=fennec:* nest start --debug --watch",
"start:prod": "node dist/main", "start:prod": "node dist/main",
"init:dev": "node docker/init-dev.mjs",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest", "test": "jest",
"test:watch": "jest --watch", "test:watch": "jest --watch",
"test:cov": "jest --coverage", "test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json" "test:e2e": "jest --config ./test/jest-e2e.json",
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js"
}, },
"dependencies": { "dependencies": {
"@fennec/configuration": "^0.0.1", "@fennec/configuration": "^0.0.2",
"@nestjs-lib/auth": "^0.2.3", "@nestjs-lib/auth": "^0.2.3",
"@nestjs-lib/etcd3": "^0.0.1", "@nestjs-lib/etcd3": "^0.0.1",
"@nestjs/common": "^8.1.1", "@nestjs/common": "^8.1.1",
@ -68,6 +70,8 @@
"eslint": "^8.0.1", "eslint": "^8.0.1",
"eslint-config-prettier": "8.3.0", "eslint-config-prettier": "8.3.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"execa": "^5.1.1",
"find-free-ports": "^3.0.0",
"jest": "^27.3.1", "jest": "^27.3.1",
"prettier": "^2.4.1", "prettier": "^2.4.1",
"supertest": "^6.1.6", "supertest": "^6.1.6",

View File

@ -26,7 +26,7 @@ import { TagsModule } from './tags/tags.module';
username: configService.get<string>('db.postgres.username'), username: configService.get<string>('db.postgres.username'),
password: configService.get<string>('db.postgres.password'), password: configService.get<string>('db.postgres.password'),
database: configService.get<string>('db.postgres.database'), database: configService.get<string>('db.postgres.database'),
synchronize: true, synchronize: false,
autoLoadEntities: true, autoLoadEntities: true,
}), }),
inject: [ConfigService], inject: [ConfigService],

View File

@ -1,3 +1,4 @@
import { ServiceRegister } from '@fennec/configuration';
import { ValidationPipe } from '@nestjs/common'; import { ValidationPipe } from '@nestjs/common';
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
import { NestFactory } from '@nestjs/core'; import { NestFactory } from '@nestjs/core';
@ -15,9 +16,11 @@ async function bootstrap() {
}), }),
); );
app.useGlobalFilters(new HttpExceptionFilter()); app.useGlobalFilters(new HttpExceptionFilter());
await app.listen(configService.get<number>('http.port')); const server = await app.listen(configService.get<number>('http.port', 0));
const port = server.address().port;
const register = new ServiceRegister({ etcd: { hosts: 'http://rpi:2379' } }); const register = new ServiceRegister({ etcd: { hosts: 'http://rpi:2379' } });
register.register('fennec/api', `http://localhost:${port}`); register.register('blog/api', `http://localhost:${port}`);
register.register('api.fennec', `http://localhost:${port}`); register.register('admin.blog/api', `http://localhost:${port}`);
register.register('api.blog', `http://localhost:${port}`);
} }
bootstrap(); bootstrap();