8 Commits

14 changed files with 860 additions and 327 deletions

View File

@@ -44,20 +44,6 @@ jobs:
steps:
- checkout
- restore_cache:
keys:
- backend-dependencies-{{ checksum "package.json" }}
- run:
name: install backend deps
command: npm i
- save_cache:
paths:
- node_modules
key: backend-dependencies-{{ checksum "package.json" }}
- restore_cache:
keys:
- frontend-dependencies-{{ checksum "frontend/package.json" }}
@@ -82,27 +68,14 @@ jobs:
docker:
- image: cimg/node:14.20
working_directory: ~/photos/frontend
working_directory: ~/photos
steps:
- checkout:
- restore_cache:
keys:
- backend-dependencies-{{ checksum "package.json" }}
- run:
name: install backend deps
command: npm i
- save_cache:
paths:
- node_modules
key: backend-dependencies-{{ checksum "package.json" }}
- restore_cache:
keys:
- frontend-dependencies-{{ checksum "package.json" }}
- frontend-dependencies-{{ checksum "frontend/package.json" }}
- run:
name: install frontend deps
@@ -111,7 +84,7 @@ jobs:
- save_cache:
paths:
- frontend/node_modules
key: frontend-dependencies-{{ checksum "package.json" }}
key: frontend-dependencies-{{ checksum "frontend/package.json" }}
- run:
name: build frontend
@@ -119,6 +92,7 @@ jobs:
build:
machine:
image: ubuntu-2004:current
docker_layer_caching: true
working_directory: ~/photos
resource_class: large
@@ -138,7 +112,7 @@ jobs:
- run:
name: build and push to docker hub
command: docker buildx build --push --platform linux/arm64,linux/amd64 --tag stepanusatiuk/photos:$CIRCLE_BRANCH .
command: docker buildx build --progress=plain --push --platform linux/arm64,linux/amd64 --tag stepanusatiuk/photos:$CIRCLE_BRANCH .
#command: docker buildx build --push --platform linux/amd64 --tag stepanusatiuk/photos:$CIRCLE_BRANCH .
# build-arm:

View File

@@ -3,3 +3,4 @@ npm-debug.log
frontend/node_modules
frontend/npm-debug.log
frontend/.parcel-cache

View File

@@ -1,21 +1,26 @@
# might fix this? https://github.com/parcel-bundler/parcel/issues/6735
FROM node:16-bullseye
FROM node:16-bullseye as frontbuild
WORKDIR /usr/src/app/frontend
COPY ./frontend/package*.json ./
RUN npm ci --only=production
COPY ./frontend .
COPY ./src/shared ../src/shared
RUN npm run build && bash -O extglob -c 'rm -rfv !("dist")'
WORKDIR ../
RUN bash -O extglob -c 'rm -rfv !("frontend")'
FROM node:16-alpine as backexceptwithoutfrontend
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci --only=production
COPY ./ ./
RUN rm -rfv frontend
RUN mkdir frontend
WORKDIR frontend
COPY ./frontend/package*.json ./
RUN npm ci --only=production
WORKDIR ../
FROM backexceptwithoutfrontend
COPY . .
WORKDIR frontend
RUN npm run build
WORKDIR ../
COPY --from=frontbuild /usr/src/app/frontend .
#ENV PORT=8080
#ENV TYPEORM_HOST=localhost

View File

@@ -1,5 +1,3 @@
#!/bin/bash
npm run typeorm -- migration:run
npm start

View File

@@ -13,6 +13,7 @@
"@typescript-eslint/eslint-plugin": "^5.48.1",
"@typescript-eslint/parser": "^5.48.1",
"@wojtekmaj/enzyme-adapter-react-17": "^0",
"class-validator": "^0.14.0",
"enzyme": "^3.11.0",
"eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.0",
@@ -2833,6 +2834,11 @@
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"node_modules/@types/validator": {
"version": "13.7.10",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.10.tgz",
"integrity": "sha512-t1yxFAR2n0+VO6hd/FJ9F2uezAZVWHLmpmlJzm1eX03+H7+HsuTAp7L8QJs+2pQCfWkP1+EXsGK9Z9v7o/qPVQ=="
},
"node_modules/@types/yargs": {
"version": "17.0.19",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz",
@@ -3811,6 +3817,16 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
},
"node_modules/class-validator": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz",
"integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==",
"dependencies": {
"@types/validator": "^13.7.10",
"libphonenumber-js": "^1.10.14",
"validator": "^13.7.0"
}
},
"node_modules/classnames": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
@@ -7057,6 +7073,11 @@
"node": ">= 0.8.0"
}
},
"node_modules/libphonenumber-js": {
"version": "1.10.18",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.18.tgz",
"integrity": "sha512-NS4ZEgNhwbcPz1gfSXCGFnQm0xEiyTSPRthIuWytDzOiEG9xnZ2FbLyfJC4tI2BMAAXpoWbNxHYH75pa3Dq9og=="
},
"node_modules/lightningcss": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.18.0.tgz",
@@ -9971,6 +9992,14 @@
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
},
"node_modules/validator": {
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/value-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
@@ -12294,6 +12323,11 @@
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"@types/validator": {
"version": "13.7.10",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.10.tgz",
"integrity": "sha512-t1yxFAR2n0+VO6hd/FJ9F2uezAZVWHLmpmlJzm1eX03+H7+HsuTAp7L8QJs+2pQCfWkP1+EXsGK9Z9v7o/qPVQ=="
},
"@types/yargs": {
"version": "17.0.19",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz",
@@ -12965,6 +12999,16 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
},
"class-validator": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz",
"integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==",
"requires": {
"@types/validator": "^13.7.10",
"libphonenumber-js": "^1.10.14",
"validator": "^13.7.0"
}
},
"classnames": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
@@ -15319,6 +15363,11 @@
"type-check": "~0.4.0"
}
},
"libphonenumber-js": {
"version": "1.10.18",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.18.tgz",
"integrity": "sha512-NS4ZEgNhwbcPz1gfSXCGFnQm0xEiyTSPRthIuWytDzOiEG9xnZ2FbLyfJC4tI2BMAAXpoWbNxHYH75pa3Dq9og=="
},
"lightningcss": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.18.0.tgz",
@@ -17406,6 +17455,11 @@
}
}
},
"validator": {
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw=="
},
"value-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",

View File

@@ -15,6 +15,7 @@
"@typescript-eslint/eslint-plugin": "^5.48.1",
"@typescript-eslint/parser": "^5.48.1",
"@wojtekmaj/enzyme-adapter-react-17": "^0",
"class-validator": "^0.14.0",
"enzyme": "^3.11.0",
"eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.0",

View File

@@ -42,7 +42,7 @@ import {
photoUploadSuccess,
} from "./actions";
import { IPhotosNewRespBody } from "../../../../src/routes/photos";
import { IPhotosListPagination } from "../../../../src/types";
import { IPhotosListPagination } from "../../../../src/shared/types";
// Thanks, https://dev.to/qortex/compute-md5-checksum-for-a-file-in-typescript-59a4
function computeChecksumMd5(file: File): Promise<string> {

987
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,23 +24,10 @@
"dependencies": {
"@koa/cors": "^3.4.1",
"@koa/router": "^12.0.0",
"@typescript-eslint/eslint-plugin": "^5.48.1",
"@typescript-eslint/parser": "^5.48.1",
"bcrypt": "^5.1.0",
"chai": "^4.3.7",
"class-validator": "^0.14.0",
"concurrently": "^7.6.0",
"cross-env": "^7.0.3",
"deasync": "^0.1.28",
"eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.0",
"eslint-import-resolver-typescript": "^3.5.3",
"eslint-plugin-import": "^2.27.4",
"eslint-plugin-mocha": "^10.1.0",
"eslint-plugin-prettier": "^4.2.1",
"exifreader": "^4.9.1",
"hasha": "^5.2.2",
"husky": "^8.0.3",
"jsonwebtoken": "^9.0.0",
"koa": "^2.14.1",
"koa-body": "^5.0.0",
@@ -50,14 +37,9 @@
"koa-sslify": "^5.0.1",
"koa-static": "^5.0.0",
"mime-types": "^2.1.35",
"mocha": "^10.2.0",
"mysql": "^2.18.1",
"prettier": "^2.8.2",
"prettier-eslint": "^15.0.1",
"sharp": "^0.31.3",
"supertest": "^6.3.3",
"ts-node": "^10.9.1",
"ts-node-dev": "^2",
"tsconfig-paths": "^4.1.2",
"typeorm": "^0.2.41",
"typescript": "^4.9.4"
@@ -83,8 +65,25 @@
"@types/prettier": "^2.7.2",
"@types/sharp": "^0.31.1",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^5.48.1",
"@typescript-eslint/parser": "^5.48.1",
"chai": "^4.3.7",
"concurrently": "^7.6.0",
"cross-env": "^7.0.3",
"eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.0",
"eslint-import-resolver-typescript": "^3.5.3",
"eslint-plugin-import": "^2.27.4",
"eslint-plugin-mocha": "^10.1.0",
"eslint-plugin-prettier": "^4.2.1",
"husky": "^8.0.3",
"mocha": "^10.2.0",
"mocha-junit-reporter": "^2.2.0",
"mocha-multi-reporters": "^1.5.1"
"mocha-multi-reporters": "^1.5.1",
"prettier": "^2.8.2",
"prettier-eslint": "^15.0.1",
"supertest": "^6.3.3",
"ts-node-dev": "^2"
},
"husky": {
"hooks": {

View File

@@ -1,7 +1,7 @@
import * as Router from "@koa/router";
import { IPhotoReqJSON, Photo } from "~entity/Photo";
import { User } from "~entity/User";
import { IAPIResponse, IPhotosListPagination } from "~types";
import { IAPIResponse, IPhotosListPagination } from "~/shared/types";
import * as fs from "fs/promises";
import send = require("koa-send");
import { getHash, getSize } from "~util";

View File

@@ -1,7 +1,7 @@
import * as Router from "@koa/router";
import { getConfigValue, ConfigKey } from "~entity/Config";
import { IUserAuthJSON, IUserJWT, User } from "~entity/User";
import { IAPIResponse } from "~types";
import { IAPIResponse } from "~/shared/types";
export const userRouter = new Router();

View File

@@ -1,3 +1,4 @@
import { Connection } from "typeorm";
import { Config, ConfigKey, setConfigValue } from "~entity/Config";
import { app } from "./app";
import { config } from "./config";
@@ -25,20 +26,31 @@ async function dumpConfig() {
console.log(`${entry.key} = ${entry.value}`);
}
}
async function migrate(connection: Connection) {
await connection.runMigrations();
console.log("Migrations ran");
}
async function startApp() {
app.listen(config.port);
console.log(`Listening at ${config.port}`);
}
connect()
.then((connection) => {
console.log(`Connected to ${connection.name}`);
const startApp = () => {
app.listen(config.port);
console.log(`Listening at ${config.port}`);
};
migrate(connection)
.then(() =>
readConfig()
.then(() =>
dumpConfig()
.then(() => startApp())
.catch((e) => console.log(e)),
)
.catch((e) => console.log(e)),
)
.catch((e) => console.log(e));
})
.catch((e) => console.log(e));

View File

@@ -1,4 +1,3 @@
import deasync = require("deasync");
import { fromFile } from "hasha";
import * as ExifReader from "exifreader";
import * as sharp from "sharp";
@@ -72,8 +71,3 @@ export async function fileCheck(file: string) {
return false;
}
}
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const getHashSync: (file: string) => string = deasync(getHash);
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const getSizeSync: (file: string) => string = deasync(getSize);