8 Commits

14 changed files with 860 additions and 327 deletions

View File

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

View File

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

View File

@@ -1,21 +1,26 @@
# might fix this? https://github.com/parcel-bundler/parcel/issues/6735 # 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 WORKDIR /usr/src/app
COPY package*.json ./ COPY package*.json ./
RUN npm ci --only=production RUN npm ci --only=production
COPY ./ ./
RUN rm -rfv frontend
RUN mkdir frontend FROM backexceptwithoutfrontend
WORKDIR frontend
COPY ./frontend/package*.json ./
RUN npm ci --only=production
WORKDIR ../
COPY . . COPY --from=frontbuild /usr/src/app/frontend .
WORKDIR frontend
RUN npm run build
WORKDIR ../
#ENV PORT=8080 #ENV PORT=8080
#ENV TYPEORM_HOST=localhost #ENV TYPEORM_HOST=localhost

View File

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

View File

@@ -13,6 +13,7 @@
"@typescript-eslint/eslint-plugin": "^5.48.1", "@typescript-eslint/eslint-plugin": "^5.48.1",
"@typescript-eslint/parser": "^5.48.1", "@typescript-eslint/parser": "^5.48.1",
"@wojtekmaj/enzyme-adapter-react-17": "^0", "@wojtekmaj/enzyme-adapter-react-17": "^0",
"class-validator": "^0.14.0",
"enzyme": "^3.11.0", "enzyme": "^3.11.0",
"eslint": "^8.31.0", "eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.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", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" "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": { "node_modules/@types/yargs": {
"version": "17.0.19", "version": "17.0.19",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz", "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", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" "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": { "node_modules/classnames": {
"version": "2.3.2", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
@@ -7057,6 +7073,11 @@
"node": ">= 0.8.0" "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": { "node_modules/lightningcss": {
"version": "1.18.0", "version": "1.18.0",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.18.0.tgz", "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", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" "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": { "node_modules/value-equal": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", "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", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" "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": { "@types/yargs": {
"version": "17.0.19", "version": "17.0.19",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz", "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", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" "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": { "classnames": {
"version": "2.3.2", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
@@ -15319,6 +15363,11 @@
"type-check": "~0.4.0" "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": { "lightningcss": {
"version": "1.18.0", "version": "1.18.0",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.18.0.tgz", "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": { "value-equal": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", "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/eslint-plugin": "^5.48.1",
"@typescript-eslint/parser": "^5.48.1", "@typescript-eslint/parser": "^5.48.1",
"@wojtekmaj/enzyme-adapter-react-17": "^0", "@wojtekmaj/enzyme-adapter-react-17": "^0",
"class-validator": "^0.14.0",
"enzyme": "^3.11.0", "enzyme": "^3.11.0",
"eslint": "^8.31.0", "eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.0", "eslint-config-prettier": "^8.6.0",

View File

@@ -42,7 +42,7 @@ import {
photoUploadSuccess, photoUploadSuccess,
} from "./actions"; } from "./actions";
import { IPhotosNewRespBody } from "../../../../src/routes/photos"; 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 // Thanks, https://dev.to/qortex/compute-md5-checksum-for-a-file-in-typescript-59a4
function computeChecksumMd5(file: File): Promise<string> { 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": { "dependencies": {
"@koa/cors": "^3.4.1", "@koa/cors": "^3.4.1",
"@koa/router": "^12.0.0", "@koa/router": "^12.0.0",
"@typescript-eslint/eslint-plugin": "^5.48.1",
"@typescript-eslint/parser": "^5.48.1",
"bcrypt": "^5.1.0", "bcrypt": "^5.1.0",
"chai": "^4.3.7",
"class-validator": "^0.14.0", "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", "exifreader": "^4.9.1",
"hasha": "^5.2.2", "hasha": "^5.2.2",
"husky": "^8.0.3",
"jsonwebtoken": "^9.0.0", "jsonwebtoken": "^9.0.0",
"koa": "^2.14.1", "koa": "^2.14.1",
"koa-body": "^5.0.0", "koa-body": "^5.0.0",
@@ -50,14 +37,9 @@
"koa-sslify": "^5.0.1", "koa-sslify": "^5.0.1",
"koa-static": "^5.0.0", "koa-static": "^5.0.0",
"mime-types": "^2.1.35", "mime-types": "^2.1.35",
"mocha": "^10.2.0",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"prettier": "^2.8.2",
"prettier-eslint": "^15.0.1",
"sharp": "^0.31.3", "sharp": "^0.31.3",
"supertest": "^6.3.3",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"ts-node-dev": "^2",
"tsconfig-paths": "^4.1.2", "tsconfig-paths": "^4.1.2",
"typeorm": "^0.2.41", "typeorm": "^0.2.41",
"typescript": "^4.9.4" "typescript": "^4.9.4"
@@ -83,8 +65,25 @@
"@types/prettier": "^2.7.2", "@types/prettier": "^2.7.2",
"@types/sharp": "^0.31.1", "@types/sharp": "^0.31.1",
"@types/supertest": "^2.0.12", "@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-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": { "husky": {
"hooks": { "hooks": {

View File

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

View File

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

View File

@@ -1,3 +1,4 @@
import { Connection } from "typeorm";
import { Config, ConfigKey, setConfigValue } from "~entity/Config"; import { Config, ConfigKey, setConfigValue } from "~entity/Config";
import { app } from "./app"; import { app } from "./app";
import { config } from "./config"; import { config } from "./config";
@@ -25,18 +26,29 @@ async function dumpConfig() {
console.log(`${entry.key} = ${entry.value}`); 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() connect()
.then((connection) => { .then((connection) => {
console.log(`Connected to ${connection.name}`); console.log(`Connected to ${connection.name}`);
const startApp = () => {
app.listen(config.port);
console.log(`Listening at ${config.port}`);
};
readConfig() migrate(connection)
.then(() => .then(() =>
dumpConfig() readConfig()
.then(() => startApp()) .then(() =>
dumpConfig()
.then(() => startApp())
.catch((e) => console.log(e)),
)
.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 { fromFile } from "hasha";
import * as ExifReader from "exifreader"; import * as ExifReader from "exifreader";
import * as sharp from "sharp"; import * as sharp from "sharp";
@@ -71,9 +70,4 @@ export async function fileCheck(file: string) {
} catch (e) { } catch (e) {
return false; 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);