diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..76ddc81 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +node_modules +npm-debug.log + +frontend/node_modules +frontend/npm-debug.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..30e9fa5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,42 @@ +FROM node:14 + +WORKDIR /usr/src/app +COPY package*.json ./ +RUN npm ci --only=production + +RUN mkdir frontend +WORKDIR frontend +COPY ./frontend/package*.json ./ +RUN npm ci --only=production +WORKDIR ../ + +COPY . . + +WORKDIR frontend +RUN npm run build +WORKDIR ../ + +ENV PORT=8080 +ENV DATA_DIR=data + +ENV TYPEORM_CONNECTION=mariadb +#ENV TYPEORM_HOST=localhost +#ENV TYPEORM_USERNAME=root +#ENV TYPEORM_PASSWORD=admin +#ENV TYPEORM_DATABASE=test +#ENV TYPEORM_PORT=3000 +ENV TYPEORM_SYNCHRONIZE=false +ENV TYPEORM_LOGGING=false +ENV TYPEORM_ENTITIES=src/entity/**/*.ts +ENV TYPEORM_ENTITIES_DIR=src/entity +ENV TYPEORM_MIGRATIONS=src/migration/**/*.ts +ENV TYPEORM_MIGRATIONS_DIR=src/migration +ENV TYPEORM_SUBSCRIBERS=src/subscriber/**/*.ts +ENV TYPEORM_SUBSCRIBERS_DIR=src/subscriber +ENV TYPEORM_DRIVER_EXTRA='{"charset": "utf8mb4"}' + +EXPOSE 8080 + +RUN ["chmod", "+x", "dockerentry.sh"] + +CMD [ "./dockerentry.sh" ] diff --git a/dockercomposeexample/db.env b/dockercomposeexample/db.env new file mode 100644 index 0000000..977649a --- /dev/null +++ b/dockercomposeexample/db.env @@ -0,0 +1,11 @@ +TYPEORM_HOST = db +TYPEORM_USERNAME = photos +TYPEORM_PASSWORD = photos +TYPEORM_DATABASE = photos +TYPEORM_PORT = 3306 +MYSQL_DATABASE = photos +MYSQL_USER = photos +MYSQL_PASSWORD = photos +MYSQL_ROOT_PASSWORD = photos + + diff --git a/dockercomposeexample/docker-compose.yml b/dockercomposeexample/docker-compose.yml new file mode 100644 index 0000000..2f2b76d --- /dev/null +++ b/dockercomposeexample/docker-compose.yml @@ -0,0 +1,24 @@ +version: "3.8" +services: + photosapp: + image: docker.io/stepanusatiuk/photos_test + ports: + - "8080:8080" + volumes: + - ./data:/usr/src/app/data + environment: + - JWT_SECRET=huegrhuigerhupoiervw + - API_ROOT=http://localhost:8080 + - WEB_ROOT=http://localhost:8080 + env_file: + - db.env + depends_on: + - db + db: + image: mariadb + restart: always + volumes: + - ./dbdata:/var/lib/mysql + env_file: + - db.env + diff --git a/dockerentry.sh b/dockerentry.sh new file mode 100644 index 0000000..eb7e055 --- /dev/null +++ b/dockerentry.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +npm run typeorm -- migration:run + +npm start \ No newline at end of file diff --git a/frontend/src/env.ts b/frontend/src/env.ts index 995525f..d9bd20a 100644 --- a/frontend/src/env.ts +++ b/frontend/src/env.ts @@ -1,2 +1,12 @@ -export const apiRoot = process.env.API_ROOT || "http://localhost:3000"; -export const webRoot = process.env.WEB_ROOT || "http://localhost:1234"; +export const apiRoot = + process.env.API_ROOT || + process.env.NODE_ENV === "production" || + !process.env.NODE_ENV + ? window.location.origin + : "http://localhost:3000"; +export const webRoot = + process.env.WEB_ROOT || + process.env.NODE_ENV === "production" || + !process.env.NODE_ENV + ? window.location.origin + : "http://localhost:1234"; diff --git a/ormconfig.dockerdevexample.json b/ormconfig.dockerdevexample.json index a95d227..e51fa99 100644 --- a/ormconfig.dockerdevexample.json +++ b/ormconfig.dockerdevexample.json @@ -5,7 +5,7 @@ "username": "photos", "password": "photos", "database": "photos", - "synchronize": true, + "synchronize": false, "logging": false, "entities": [ "src/entity/**/*.ts" diff --git a/ormconfig.example.json b/ormconfig.example.json index f497771..85cc09b 100644 --- a/ormconfig.example.json +++ b/ormconfig.example.json @@ -5,7 +5,7 @@ "username": "photos", "password": "photos", "database": "photos", - "synchronize": true, + "synchronize": false, "logging": false, "entities": [ "src/entity/**/*.ts" diff --git a/package.json b/package.json index c38ca60..53d1593 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "prettier-check": "prettier src/**/*.ts frontend/src/**/*.ts frontend/src/**/*.tsx --check", "prettify": "prettier src/**/*.ts frontend/src/**/*.ts frontend/src/**/*.tsx --write", "typeorm-dev": "cross-env NODE_ENV=development ts-node -T -r tsconfig-paths/register ./node_modules/typeorm/cli.js", - "typeorm": "ts-node -T -r tsconfig-paths/register ./node_modules/typeorm/cli.js" + "typeorm": "cross-env NODE_ENV=development ts-node -T -r tsconfig-paths/register ./node_modules/typeorm/cli.js" }, "license": "MIT", "dependencies": { @@ -89,4 +89,4 @@ "pre-commit": "npm run lint-all && npm run prettier-check" } } -} +} \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index 2754a90..7387db3 100644 --- a/src/app.ts +++ b/src/app.ts @@ -32,7 +32,7 @@ app.use( }), ); -if (config.env === EnvType.production) { +if (config.https) { app.use(sslify({ resolver: xForwardedProtoResolver })); } app.use( diff --git a/src/config/index.ts b/src/config/index.ts index 8e2da58..949bc92 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -12,6 +12,7 @@ export interface IConfig { port: number; jwtSecret: string; dataDir: string; + https: boolean; dbConnectionOptions: ConnectionOptions | null; } @@ -59,6 +60,7 @@ function getDataDir(): string { const production: IConfig = { env: EnvType.production, port: process.env.PORT ? parseInt(process.env.PORT, 10) : 3000, + https: process.env.HTTPS ? process.env.HTTPS === "yes" : false, jwtSecret: getJwtSecret(), dataDir: getDataDir(), dbConnectionOptions: null, diff --git a/src/migration/1603126879697-init.ts b/src/migration/1603126879697-init.ts new file mode 100644 index 0000000..74e148f --- /dev/null +++ b/src/migration/1603126879697-init.ts @@ -0,0 +1,22 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class init1603126879697 implements MigrationInterface { + name = 'init1603126879697' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query("CREATE TABLE `user` (`id` int NOT NULL AUTO_INCREMENT, `username` varchar(190) NOT NULL, `email` varchar(190) NOT NULL, `passwordHash` varchar(190) NOT NULL, UNIQUE INDEX `IDX_78a916df40e02a9deb1c4b75ed` (`username`), UNIQUE INDEX `IDX_e12875dfb3b1d92d7d7c5377e2` (`email`), PRIMARY KEY (`id`)) ENGINE=InnoDB"); + await queryRunner.query("CREATE TABLE `photo` (`id` int NOT NULL AUTO_INCREMENT, `hash` varchar(190) NOT NULL, `size` varchar(190) NOT NULL, `format` varchar(190) NOT NULL, `uploaded` tinyint NOT NULL DEFAULT 0, `generatedThumbs` set ('512', '1024', '2048') NOT NULL DEFAULT '', `accessToken` varchar(500) NOT NULL, `accessTokenExpiry` timestamp NULL DEFAULT NULL, `shotAt` timestamp NULL DEFAULT NULL, `createdAt` timestamp NULL DEFAULT NULL, `editedAt` timestamp NULL DEFAULT NULL, `userId` int NULL, INDEX `IDX_43d1a6df29f544bdc57ab4cdc6` (`hash`), UNIQUE INDEX `IDX_491fe52f7ce0f0696fc0b70e7f` (`hash`, `size`, `userId`), PRIMARY KEY (`id`)) ENGINE=InnoDB"); + await queryRunner.query("ALTER TABLE `photo` ADD CONSTRAINT `FK_4494006ff358f754d07df5ccc87` FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION"); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `photo` DROP FOREIGN KEY `FK_4494006ff358f754d07df5ccc87`"); + await queryRunner.query("DROP INDEX `IDX_491fe52f7ce0f0696fc0b70e7f` ON `photo`"); + await queryRunner.query("DROP INDEX `IDX_43d1a6df29f544bdc57ab4cdc6` ON `photo`"); + await queryRunner.query("DROP TABLE `photo`"); + await queryRunner.query("DROP INDEX `IDX_e12875dfb3b1d92d7d7c5377e2` ON `user`"); + await queryRunner.query("DROP INDEX `IDX_78a916df40e02a9deb1c4b75ed` ON `user`"); + await queryRunner.query("DROP TABLE `user`"); + } + +}