From 62a4c91ba7d553269538d5973d423c799aa372ba Mon Sep 17 00:00:00 2001 From: rubikscraft Date: Sun, 28 Aug 2022 16:31:20 +0200 Subject: [PATCH] Fix everything needed for correct build --- .dockerignore | 22 ++- README.md | 4 +- backend/nest-cli.json | 5 +- backend/package.json | 2 + backend/src/app.module.ts | 10 +- .../collections/image-db/image-db.module.ts | 6 +- .../collections/image-db/image-db.service.ts | 6 +- .../image-db/image-file-db.service.ts | 4 +- .../preference-db/preference-db.module.ts | 4 +- .../sys-preference-db.service.ts | 8 +- .../usr-preference-db.service.ts | 8 +- .../src/collections/role-db/role-db.module.ts | 2 +- .../collections/role-db/role-db.service.ts | 5 +- .../src/collections/user-db/user-db.module.ts | 2 +- .../collections/user-db/user-db.service.ts | 2 +- .../src/config/early/auth.config.service.ts | 5 +- .../config/early/early-jwt.config.service.ts | 9 +- .../src/config/early/host.config.service.ts | 32 ++-- .../config/early/multipart.config.service.ts | 5 +- .../early/serve-static.config.service.ts | 10 +- .../config/early/type-orm.config.service.ts | 42 ++-- backend/src/config/late/jwt.config.service.ts | 10 +- backend/src/database/database.module.ts | 14 ++ .../entities/image-derivative.entity.ts | 0 .../entities/image-file.entity.ts | 0 .../entities/image.entity.ts | 0 .../{models => database}/entities/index.ts | 0 .../entities/role.entity.ts | 2 +- .../entities/sys-preference.entity.ts | 0 .../entities/user.entity.ts | 0 .../entities/usr-preference.entity.ts | 0 .../migrations/1661692206479-V_0_3_0_a.ts | 44 +++++ backend/src/database/migrations/index.ts | 3 + backend/src/datasource.ts | 35 ++++ backend/src/logger/logger.service.ts | 1 - backend/src/main.ts | 10 +- backend/src/managers/auth/guest.service.ts | 2 +- backend/src/managers/image/image.service.ts | 6 +- .../models/transformers/user.transformer.ts | 2 +- backend/tsconfig.build.json | 5 - backend/tsconfig.json | 5 + frontend/angular.json | 11 +- frontend/custom-webpack.config.js | 7 + frontend/package.json | 2 + package.json | 5 +- shared/src/dto/api/image.dto.ts | 19 +- shared/src/util/parse-simple.ts | 34 ++++ support/build.sh | 15 +- support/dev.docker-compose.yml | 4 +- support/picsur.Dockerfile | 18 +- support/picsur.docker-compose.yml | 7 +- support/purge-all.sh | 8 +- yarn.lock | 180 +++++++++++++++++- 53 files changed, 490 insertions(+), 152 deletions(-) create mode 100644 backend/src/database/database.module.ts rename backend/src/{models => database}/entities/image-derivative.entity.ts (100%) rename backend/src/{models => database}/entities/image-file.entity.ts (100%) rename backend/src/{models => database}/entities/image.entity.ts (100%) rename backend/src/{models => database}/entities/index.ts (100%) rename backend/src/{models => database}/entities/role.entity.ts (83%) rename backend/src/{models => database}/entities/sys-preference.entity.ts (100%) rename backend/src/{models => database}/entities/user.entity.ts (100%) rename backend/src/{models => database}/entities/usr-preference.entity.ts (100%) create mode 100644 backend/src/database/migrations/1661692206479-V_0_3_0_a.ts create mode 100644 backend/src/database/migrations/index.ts create mode 100644 backend/src/datasource.ts delete mode 100644 backend/tsconfig.build.json create mode 100644 frontend/custom-webpack.config.js create mode 100644 shared/src/util/parse-simple.ts diff --git a/.dockerignore b/.dockerignore index 173e8ce..b22adf6 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,8 +1,22 @@ node_modules **/node_modules -dist -**/dist -Dockerfile -docker-compose.yml support +backend/dist +frontend/dist +shared/dist +**/.angular + +.yarn/* +!.yarn/patches +!.yarn/releases +!.yarn/plugins +!.yarn/sdks +!.yarn/versions +.pnp.* + +yarn-error.log +temp + +.vscode +.git diff --git a/README.md b/README.md index 78b4615..2e79f91 100644 --- a/README.md +++ b/README.md @@ -77,9 +77,9 @@ services: PICSUR_DB_HOST: picsur_postgres # PICSUR_DB_PORT: 5432 - # PICSUR_DB_USER: picsur + # PICSUR_DB_USERNAME: picsur # PICSUR_DB_PASSWORD: picsur - # PICSUR_DB_NAME: picsur + # PICSUR_DB_DATABASE: picsur # PICSUR_ADMIN_PASSWORD: picsur diff --git a/backend/nest-cli.json b/backend/nest-cli.json index 7418f27..1f0479d 100644 --- a/backend/nest-cli.json +++ b/backend/nest-cli.json @@ -6,7 +6,6 @@ "spec": false }, "compilerOptions": { - "tsConfigPath": "tsconfig.build.json" - }, - "exec": "pog" + "tsConfigPath": "tsconfig.json" + } } diff --git a/backend/package.json b/backend/package.json index 9756737..a2c939d 100644 --- a/backend/package.json +++ b/backend/package.json @@ -14,6 +14,8 @@ "start:dev": "yarn clean && nest start --watch --exec \"node --es-module-specifier-resolution=node\"", "start:debug": "nest start --debug --watch --exec \"node --es-module-specifier-resolution=node\"", "start:prod": "node --es-module-specifier-resolution=node dist/main", + "typeorm": "typeorm-ts-node-esm", + "migrate": "yarn typeorm migration:generate -d ./src/datasource.ts", "format": "prettier --write \"src/**/*.ts\"", "clean": "rimraf dist", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 304e19b..be513ef 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -1,11 +1,10 @@ import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common'; import { ServeStaticModule } from '@nestjs/serve-static'; -import { TypeOrmModule } from '@nestjs/typeorm'; import cors from 'cors'; import { IncomingMessage, ServerResponse } from 'http'; import { EarlyConfigModule } from './config/early/early-config.module'; import { ServeStaticConfigService } from './config/early/serve-static.config.service'; -import { TypeOrmConfigService } from './config/early/type-orm.config.service'; +import { DatabaseModule } from './database/database.module'; import { PicsurLoggerModule } from './logger/logger.module'; import { AuthManagerModule } from './managers/auth/auth.module'; import { DemoManagerModule } from './managers/demo/demo.module'; @@ -37,15 +36,12 @@ const imageCorsOverride = ( @Module({ imports: [ - TypeOrmModule.forRootAsync({ - useExisting: TypeOrmConfigService, - imports: [EarlyConfigModule], - }), + PicsurLoggerModule, ServeStaticModule.forRootAsync({ useExisting: ServeStaticConfigService, imports: [EarlyConfigModule], }), - PicsurLoggerModule, + DatabaseModule, AuthManagerModule, DemoManagerModule, PicsurRoutesModule, diff --git a/backend/src/collections/image-db/image-db.module.ts b/backend/src/collections/image-db/image-db.module.ts index 54af547..48e51f5 100644 --- a/backend/src/collections/image-db/image-db.module.ts +++ b/backend/src/collections/image-db/image-db.module.ts @@ -1,8 +1,8 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { EImageDerivativeBackend } from '../../models/entities/image-derivative.entity'; -import { EImageFileBackend } from '../../models/entities/image-file.entity'; -import { EImageBackend } from '../../models/entities/image.entity'; +import { EImageDerivativeBackend } from '../../database/entities/image-derivative.entity'; +import { EImageFileBackend } from '../../database/entities/image-file.entity'; +import { EImageBackend } from '../../database/entities/image.entity'; import { ImageDBService } from './image-db.service'; import { ImageFileDBService } from './image-file-db.service'; diff --git a/backend/src/collections/image-db/image-db.service.ts b/backend/src/collections/image-db/image-db.service.ts index 050d195..d7169d5 100644 --- a/backend/src/collections/image-db/image-db.service.ts +++ b/backend/src/collections/image-db/image-db.service.ts @@ -3,9 +3,9 @@ import { InjectRepository } from '@nestjs/typeorm'; import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types'; import { FindResult } from 'picsur-shared/dist/types/find-result'; import { In, Repository } from 'typeorm'; -import { EImageDerivativeBackend } from '../../models/entities/image-derivative.entity'; -import { EImageFileBackend } from '../../models/entities/image-file.entity'; -import { EImageBackend } from '../../models/entities/image.entity'; +import { EImageDerivativeBackend } from '../../database/entities/image-derivative.entity'; +import { EImageFileBackend } from '../../database/entities/image-file.entity'; +import { EImageBackend } from '../../database/entities/image.entity'; @Injectable() export class ImageDBService { diff --git a/backend/src/collections/image-db/image-file-db.service.ts b/backend/src/collections/image-db/image-file-db.service.ts index 5f67a77..dbf692b 100644 --- a/backend/src/collections/image-db/image-file-db.service.ts +++ b/backend/src/collections/image-db/image-file-db.service.ts @@ -3,8 +3,8 @@ import { InjectRepository } from '@nestjs/typeorm'; import { ImageEntryVariant } from 'picsur-shared/dist/dto/image-entry-variant.enum'; import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types'; import { LessThan, Repository } from 'typeorm'; -import { EImageDerivativeBackend } from '../../models/entities/image-derivative.entity'; -import { EImageFileBackend } from '../../models/entities/image-file.entity'; +import { EImageDerivativeBackend } from '../../database/entities/image-derivative.entity'; +import { EImageFileBackend } from '../../database/entities/image-file.entity'; const A_DAY_IN_SECONDS = 24 * 60 * 60; diff --git a/backend/src/collections/preference-db/preference-db.module.ts b/backend/src/collections/preference-db/preference-db.module.ts index 56cae62..76e30cb 100644 --- a/backend/src/collections/preference-db/preference-db.module.ts +++ b/backend/src/collections/preference-db/preference-db.module.ts @@ -1,8 +1,8 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { EarlyConfigModule } from '../../config/early/early-config.module'; -import { ESysPreferenceBackend } from '../../models/entities/sys-preference.entity'; -import { EUsrPreferenceBackend } from '../../models/entities/usr-preference.entity'; +import { ESysPreferenceBackend } from '../../database/entities/sys-preference.entity'; +import { EUsrPreferenceBackend } from '../../database/entities/usr-preference.entity'; import { PreferenceCommonService } from './preference-common.service'; import { PreferenceDefaultsService } from './preference-defaults.service'; import { SysPreferenceService } from './sys-preference-db.service'; diff --git a/backend/src/collections/preference-db/sys-preference-db.service.ts b/backend/src/collections/preference-db/sys-preference-db.service.ts index 00c8f8f..00324b5 100644 --- a/backend/src/collections/preference-db/sys-preference-db.service.ts +++ b/backend/src/collections/preference-db/sys-preference-db.service.ts @@ -8,14 +8,14 @@ import { import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum'; import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import { Repository } from 'typeorm'; +import { + ESysPreferenceBackend, + ESysPreferenceSchema +} from '../../database/entities/sys-preference.entity'; import { SysPreferenceList, SysPreferenceValueTypes } from '../../models/constants/syspreferences.const'; -import { - ESysPreferenceBackend, - ESysPreferenceSchema -} from '../../models/entities/sys-preference.entity'; import { MutexFallBack } from '../../models/util/mutex-fallback'; import { PreferenceCommonService } from './preference-common.service'; import { PreferenceDefaultsService } from './preference-defaults.service'; diff --git a/backend/src/collections/preference-db/usr-preference-db.service.ts b/backend/src/collections/preference-db/usr-preference-db.service.ts index 2c9f8dd..0bb0361 100644 --- a/backend/src/collections/preference-db/usr-preference-db.service.ts +++ b/backend/src/collections/preference-db/usr-preference-db.service.ts @@ -8,14 +8,14 @@ import { import { UsrPreference } from 'picsur-shared/dist/dto/usr-preferences.enum'; import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import { Repository } from 'typeorm'; +import { + EUsrPreferenceBackend, + EUsrPreferenceSchema +} from '../../database/entities/usr-preference.entity'; import { UsrPreferenceList, UsrPreferenceValueTypes } from '../../models/constants/usrpreferences.const'; -import { - EUsrPreferenceBackend, - EUsrPreferenceSchema -} from '../../models/entities/usr-preference.entity'; import { MutexFallBack } from '../../models/util/mutex-fallback'; import { PreferenceCommonService } from './preference-common.service'; import { PreferenceDefaultsService } from './preference-defaults.service'; diff --git a/backend/src/collections/role-db/role-db.module.ts b/backend/src/collections/role-db/role-db.module.ts index 58ea97d..2c7e75c 100644 --- a/backend/src/collections/role-db/role-db.module.ts +++ b/backend/src/collections/role-db/role-db.module.ts @@ -3,12 +3,12 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { HasFailed } from 'picsur-shared/dist/types'; import { EarlyConfigModule } from '../../config/early/early-config.module'; import { HostConfigService } from '../../config/early/host.config.service'; +import { ERoleBackend } from '../../database/entities/role.entity'; import { ImmutableRolesList, SystemRoleDefaults, SystemRolesList } from '../../models/constants/roles.const'; -import { ERoleBackend } from '../../models/entities/role.entity'; import { RolesService } from './role-db.service'; @Module({ diff --git a/backend/src/collections/role-db/role-db.service.ts b/backend/src/collections/role-db/role-db.service.ts index 0bcd490..39299e3 100644 --- a/backend/src/collections/role-db/role-db.service.ts +++ b/backend/src/collections/role-db/role-db.service.ts @@ -10,12 +10,12 @@ import { } from 'picsur-shared/dist/types'; import { makeUnique } from 'picsur-shared/dist/util/unique'; import { In, Repository } from 'typeorm'; +import { ERoleBackend } from '../../database/entities/role.entity'; import { Permissions } from '../../models/constants/permissions.const'; import { ImmutableRolesList, UndeletableRolesList } from '../../models/constants/roles.const'; -import { ERoleBackend } from '../../models/entities/role.entity'; @Injectable() export class RolesService { @@ -24,7 +24,8 @@ export class RolesService { constructor( @InjectRepository(ERoleBackend) private readonly rolesRepository: Repository, - ) {} + ) { + } public async create( name: string, diff --git a/backend/src/collections/user-db/user-db.module.ts b/backend/src/collections/user-db/user-db.module.ts index 4531f2e..234c464 100644 --- a/backend/src/collections/user-db/user-db.module.ts +++ b/backend/src/collections/user-db/user-db.module.ts @@ -4,7 +4,7 @@ import { HasFailed } from 'picsur-shared/dist/types'; import { generateRandomString } from 'picsur-shared/dist/util/random'; import { AuthConfigService } from '../../config/early/auth.config.service'; import { EarlyConfigModule } from '../../config/early/early-config.module'; -import { EUserBackend } from '../../models/entities/user.entity'; +import { EUserBackend } from '../../database/entities/user.entity'; import { PreferenceModule } from '../preference-db/preference-db.module'; import { RolesModule } from '../role-db/role-db.module'; import { UsersService } from './user-db.service'; diff --git a/backend/src/collections/user-db/user-db.service.ts b/backend/src/collections/user-db/user-db.service.ts index 7233fdb..bd63e80 100644 --- a/backend/src/collections/user-db/user-db.service.ts +++ b/backend/src/collections/user-db/user-db.service.ts @@ -12,6 +12,7 @@ import { import { FindResult } from 'picsur-shared/dist/types/find-result'; import { makeUnique } from 'picsur-shared/dist/util/unique'; import { Repository } from 'typeorm'; +import { EUserBackend } from '../../database/entities/user.entity'; import { Permissions } from '../../models/constants/permissions.const'; import { DefaultRolesList, @@ -22,7 +23,6 @@ import { LockedLoginUsersList, UndeletableUsersList } from '../../models/constants/special-users.const'; -import { EUserBackend } from '../../models/entities/user.entity'; import { GetCols } from '../../models/util/collection'; import { SysPreferenceService } from '../preference-db/sys-preference-db.service'; import { RolesService } from '../role-db/role-db.service'; diff --git a/backend/src/config/early/auth.config.service.ts b/backend/src/config/early/auth.config.service.ts index 636ff99..5c8bc4a 100644 --- a/backend/src/config/early/auth.config.service.ts +++ b/backend/src/config/early/auth.config.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; +import { ParseString } from 'picsur-shared/dist/util/parse-simple'; import { EnvPrefix } from '../config.static'; @Injectable() @@ -7,8 +8,8 @@ export class AuthConfigService { constructor(private readonly configService: ConfigService) {} public getDefaultAdminPassword(): string { - return this.configService.get( - `${EnvPrefix}ADMIN_PASSWORD`, + return ParseString( + this.configService.get(`${EnvPrefix}ADMIN_PASSWORD`), 'admin', ); } diff --git a/backend/src/config/early/early-jwt.config.service.ts b/backend/src/config/early/early-jwt.config.service.ts index b557a5f..a1dca79 100644 --- a/backend/src/config/early/early-jwt.config.service.ts +++ b/backend/src/config/early/early-jwt.config.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; +import { ParseString } from 'picsur-shared/dist/util/parse-simple'; import { EnvPrefix } from '../config.static'; @Injectable() @@ -7,10 +8,14 @@ export class EarlyJwtConfigService { constructor(private readonly configService: ConfigService) {} public getJwtSecret(): string | undefined { - return this.configService.get(`${EnvPrefix}JWT_SECRET`); + return ( + ParseString(this.configService.get(`${EnvPrefix}JWT_SECRET`)) ?? undefined + ); } public getJwtExpiresIn(): string | undefined { - return this.configService.get(`${EnvPrefix}JWT_EXPIRY`); + return ( + ParseString(this.configService.get(`${EnvPrefix}JWT_EXPIRY`)) ?? undefined + ); } } diff --git a/backend/src/config/early/host.config.service.ts b/backend/src/config/early/host.config.service.ts index d212034..9992e22 100644 --- a/backend/src/config/early/host.config.service.ts +++ b/backend/src/config/early/host.config.service.ts @@ -1,5 +1,10 @@ import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; +import { + ParseBool, + ParseInt, + ParseString +} from 'picsur-shared/dist/util/parse-simple'; import { EnvPrefix } from '../config.static'; @Injectable() @@ -7,6 +12,7 @@ export class HostConfigService { private readonly logger = new Logger('HostConfigService'); constructor(private readonly configService: ConfigService) { + this.logger.log('Production: ' + this.isProduction()); this.logger.log('Host: ' + this.getHost()); this.logger.log('Port: ' + this.getPort()); this.logger.log('Demo: ' + this.isDemo()); @@ -14,41 +20,29 @@ export class HostConfigService { } public getHost(): string { - const host = this.configService.get(`${EnvPrefix}HOST`, '0.0.0.0'); - return host; + return ParseString(this.configService.get(`${EnvPrefix}HOST`), '0.0.0.0'); } public getPort(): number { - const port = this.configService.get(`${EnvPrefix}PORT`, 8080); - return port; + return ParseInt(this.configService.get(`${EnvPrefix}PORT`), 8080); } public isDemo() { - const enabled = this.configService.get(`${EnvPrefix}DEMO`, false); - return enabled; + return ParseBool(this.configService.get(`${EnvPrefix}DEMO`), false); } public getDemoInterval() { - const interval = this.configService.get( - `${EnvPrefix}DEMO_INTERVAL`, + return ParseInt( + this.configService.get(`${EnvPrefix}DEMO_INTERVAL`), 1000 * 60 * 5, ); - return interval; } public isProduction() { - const enabled = this.configService.get( - `${EnvPrefix}PRODUCTION`, - false, - ); - return enabled; + return ParseBool(this.configService.get(`${EnvPrefix}PRODUCTION`), false); } public getVersion() { - const version = this.configService.get( - `npm_package_version`, - '0.0.0', - ); - return version; + return ParseString(this.configService.get(`npm_package_version`), '0.0.0'); } } diff --git a/backend/src/config/early/multipart.config.service.ts b/backend/src/config/early/multipart.config.service.ts index 941a27f..3625130 100644 --- a/backend/src/config/early/multipart.config.service.ts +++ b/backend/src/config/early/multipart.config.service.ts @@ -1,5 +1,6 @@ import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; +import { ParseInt } from 'picsur-shared/dist/util/parse-simple'; import { EnvPrefix } from '../config.static'; @Injectable() @@ -11,8 +12,8 @@ export class MultipartConfigService { } public getMaxFileSize(): number { - return this.configService.get( - `${EnvPrefix}MAX_FILE_SIZE`, + return ParseInt( + this.configService.get(`${EnvPrefix}MAX_FILE_SIZE`), 128000000, ); } diff --git a/backend/src/config/early/serve-static.config.service.ts b/backend/src/config/early/serve-static.config.service.ts index 3babf47..3ad0168 100644 --- a/backend/src/config/early/serve-static.config.service.ts +++ b/backend/src/config/early/serve-static.config.service.ts @@ -5,6 +5,7 @@ import { ServeStaticModuleOptionsFactory } from '@nestjs/serve-static'; import { join } from 'path'; +import { ParseString } from 'picsur-shared/dist/util/parse-simple'; import { EnvPrefix, PackageRoot } from '../config.static'; @Injectable() @@ -20,11 +21,12 @@ export class ServeStaticConfigService } public getStaticDirectory(): string { - const directory = this.configService.get( - `${EnvPrefix}STATIC_FRONTEND_ROOT`, - this.defaultLocation, + return ParseString( + this.configService.get( + `${EnvPrefix}STATIC_FRONTEND_ROOT`, + this.defaultLocation, + ), ); - return directory; } public createLoggerOptions(): ServeStaticModuleOptions[] { diff --git a/backend/src/config/early/type-orm.config.service.ts b/backend/src/config/early/type-orm.config.service.ts index bb88e97..15d88ab 100644 --- a/backend/src/config/early/type-orm.config.service.ts +++ b/backend/src/config/early/type-orm.config.service.ts @@ -1,7 +1,9 @@ import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm'; -import { EntityList } from '../../models/entities'; +import { TypeOrmOptionsFactory } from '@nestjs/typeorm'; +import { ParseInt, ParseString } from 'picsur-shared/dist/util/parse-simple'; +import { EntityList } from '../../database/entities'; +import { MigrationList } from '../../database/migrations'; import { DefaultName, EnvPrefix } from '../config.static'; import { HostConfigService } from './host.config.service'; @@ -25,31 +27,45 @@ export class TypeOrmConfigService implements TypeOrmOptionsFactory { public getTypeOrmServerOptions() { const varOptions = { - host: this.configService.get(`${EnvPrefix}DB_HOST`, 'localhost'), - port: this.configService.get(`${EnvPrefix}DB_PORT`, 5432), - username: this.configService.get( - `${EnvPrefix}DB_USERNAME`, + host: ParseString( + this.configService.get(`${EnvPrefix}DB_HOST`), + 'localhost', + ), + port: ParseInt( + this.configService.get(`${EnvPrefix}DB_PORT`), + 5432, + ), + username: ParseString( + this.configService.get(`${EnvPrefix}DB_USERNAME`), DefaultName, ), - password: this.configService.get( - `${EnvPrefix}DB_PASSWORD`, + password: ParseString( + this.configService.get(`${EnvPrefix}DB_PASSWORD`), DefaultName, ), - database: this.configService.get( - `${EnvPrefix}DB_DATABASE`, + database: ParseString( + this.configService.get(`${EnvPrefix}DB_DATABASE`), DefaultName, ), }; return varOptions; } - public createTypeOrmOptions(connectionName?: string): TypeOrmModuleOptions { + public createTypeOrmOptions(connectionName?: string) { const varOptions = this.getTypeOrmServerOptions(); return { - type: 'postgres', - synchronize: !this.hostService.isProduction(), + type: 'postgres' as 'postgres', + synchronize: false, + + migrationsRun: true, entities: EntityList, + migrations: MigrationList, + + cli: { + migrationsDir: 'src/database/migrations', + entitiesDir: 'src/database/entities', + }, ...varOptions, }; diff --git a/backend/src/config/late/jwt.config.service.ts b/backend/src/config/late/jwt.config.service.ts index e97adba..e61a4fd 100644 --- a/backend/src/config/late/jwt.config.service.ts +++ b/backend/src/config/late/jwt.config.service.ts @@ -1,5 +1,6 @@ import { FactoryProvider, Injectable, Logger } from '@nestjs/common'; import { JwtModuleOptions, JwtOptionsFactory } from '@nestjs/jwt'; +import ms from 'ms'; import { ThrowIfFailed } from 'picsur-shared/dist/types'; import { SysPreferenceService } from '../../collections/preference-db/sys-preference-db.service'; @@ -26,12 +27,17 @@ export class JwtConfigService implements JwtOptionsFactory { return secret; } - public async getJwtExpiresIn(): Promise { + public async getJwtExpiresIn(): Promise { const expiresIn = ThrowIfFailed( await this.prefService.getStringPreference('jwt_expires_in'), ); - return expiresIn; + let milliseconds = ms(expiresIn); + if (milliseconds === undefined) { + milliseconds = 1000 * 60 * 60 * 24; // 1 day + } + + return milliseconds / 1000; } public async createJwtOptions(): Promise { diff --git a/backend/src/database/database.module.ts b/backend/src/database/database.module.ts new file mode 100644 index 0000000..fbf02a4 --- /dev/null +++ b/backend/src/database/database.module.ts @@ -0,0 +1,14 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { EarlyConfigModule } from '../config/early/early-config.module'; +import { TypeOrmConfigService } from '../config/early/type-orm.config.service'; + +@Module({ + imports: [ + TypeOrmModule.forRootAsync({ + useExisting: TypeOrmConfigService, + imports: [EarlyConfigModule], + }), + ], +}) +export class DatabaseModule {} diff --git a/backend/src/models/entities/image-derivative.entity.ts b/backend/src/database/entities/image-derivative.entity.ts similarity index 100% rename from backend/src/models/entities/image-derivative.entity.ts rename to backend/src/database/entities/image-derivative.entity.ts diff --git a/backend/src/models/entities/image-file.entity.ts b/backend/src/database/entities/image-file.entity.ts similarity index 100% rename from backend/src/models/entities/image-file.entity.ts rename to backend/src/database/entities/image-file.entity.ts diff --git a/backend/src/models/entities/image.entity.ts b/backend/src/database/entities/image.entity.ts similarity index 100% rename from backend/src/models/entities/image.entity.ts rename to backend/src/database/entities/image.entity.ts diff --git a/backend/src/models/entities/index.ts b/backend/src/database/entities/index.ts similarity index 100% rename from backend/src/models/entities/index.ts rename to backend/src/database/entities/index.ts diff --git a/backend/src/models/entities/role.entity.ts b/backend/src/database/entities/role.entity.ts similarity index 83% rename from backend/src/models/entities/role.entity.ts rename to backend/src/database/entities/role.entity.ts index fae3cde..9f7cc0d 100644 --- a/backend/src/models/entities/role.entity.ts +++ b/backend/src/database/entities/role.entity.ts @@ -1,6 +1,6 @@ import { ERole } from 'picsur-shared/dist/entities/role.entity'; import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; -import type { Permissions } from '../constants/permissions.const'; +import type { Permissions } from '../../models/constants/permissions.const'; @Entity() export class ERoleBackend implements ERole { diff --git a/backend/src/models/entities/sys-preference.entity.ts b/backend/src/database/entities/sys-preference.entity.ts similarity index 100% rename from backend/src/models/entities/sys-preference.entity.ts rename to backend/src/database/entities/sys-preference.entity.ts diff --git a/backend/src/models/entities/user.entity.ts b/backend/src/database/entities/user.entity.ts similarity index 100% rename from backend/src/models/entities/user.entity.ts rename to backend/src/database/entities/user.entity.ts diff --git a/backend/src/models/entities/usr-preference.entity.ts b/backend/src/database/entities/usr-preference.entity.ts similarity index 100% rename from backend/src/models/entities/usr-preference.entity.ts rename to backend/src/database/entities/usr-preference.entity.ts diff --git a/backend/src/database/migrations/1661692206479-V_0_3_0_a.ts b/backend/src/database/migrations/1661692206479-V_0_3_0_a.ts new file mode 100644 index 0000000..45d3c87 --- /dev/null +++ b/backend/src/database/migrations/1661692206479-V_0_3_0_a.ts @@ -0,0 +1,44 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class V030A1661692206479 implements MigrationInterface { + name = 'V030A1661692206479' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "e_image_derivative_backend" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "image_id" character varying NOT NULL, "key" character varying NOT NULL, "filetype" character varying NOT NULL, "last_read" TIMESTAMP NOT NULL, "data" bytea NOT NULL, CONSTRAINT "UQ_fa03f5333afd74c5cc5ff780d75" UNIQUE ("image_id", "key"), CONSTRAINT "PK_ff1ecff935b8d7bdcea89087810" PRIMARY KEY ("_id"))`); + await queryRunner.query(`CREATE INDEX "IDX_37055605f39b3f8847232d604f" ON "e_image_derivative_backend" ("image_id") `); + await queryRunner.query(`CREATE INDEX "IDX_7dc534a666f442383341896062" ON "e_image_derivative_backend" ("key") `); + await queryRunner.query(`CREATE TABLE "e_image_file_backend" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "image_id" character varying NOT NULL, "variant" character varying NOT NULL, "filetype" character varying NOT NULL, "data" bytea NOT NULL, CONSTRAINT "UQ_872384f20feaf7bfd27e28b8d4a" UNIQUE ("image_id", "variant"), CONSTRAINT "PK_95953be58a506e5de46feec6186" PRIMARY KEY ("_id"))`); + await queryRunner.query(`CREATE INDEX "IDX_8055f37d3b9f52f421b94ee84d" ON "e_image_file_backend" ("image_id") `); + await queryRunner.query(`CREATE INDEX "IDX_d0500b00b0b4109b623f897c2d" ON "e_image_file_backend" ("variant") `); + await queryRunner.query(`CREATE TABLE "e_image_backend" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "user_id" character varying NOT NULL, "created" TIMESTAMP NOT NULL, CONSTRAINT "PK_5f7993001a7c82564ec5300540d" PRIMARY KEY ("id"))`); + await queryRunner.query(`CREATE TABLE "e_role_backend" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying NOT NULL, "permissions" text array NOT NULL, CONSTRAINT "UQ_cbedb9f42a98a82d91422e7fedf" UNIQUE ("name"), CONSTRAINT "PK_af7ba6a46bf69a7b10c425f0367" PRIMARY KEY ("id"))`); + await queryRunner.query(`CREATE INDEX "IDX_cbedb9f42a98a82d91422e7fed" ON "e_role_backend" ("name") `); + await queryRunner.query(`CREATE TABLE "e_sys_preference_backend" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "key" character varying NOT NULL, "value" character varying NOT NULL, CONSTRAINT "UQ_b04e47c4814fb6e315c5879fa75" UNIQUE ("key"), CONSTRAINT "PK_b79f051e19b46e74cf255e9ba3b" PRIMARY KEY ("id"))`); + await queryRunner.query(`CREATE INDEX "IDX_b04e47c4814fb6e315c5879fa7" ON "e_sys_preference_backend" ("key") `); + await queryRunner.query(`CREATE TABLE "e_user_backend" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "username" character varying NOT NULL, "roles" text array NOT NULL, "hashed_password" character varying NOT NULL, CONSTRAINT "UQ_ae538430fd08b28f4ab297eff09" UNIQUE ("username"), CONSTRAINT "PK_0b9d256d52e55a48d32e8b64d96" PRIMARY KEY ("id"))`); + await queryRunner.query(`CREATE INDEX "IDX_ae538430fd08b28f4ab297eff0" ON "e_user_backend" ("username") `); + await queryRunner.query(`CREATE TABLE "e_usr_preference_backend" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "key" character varying NOT NULL, "value" character varying NOT NULL, "user_id" character varying NOT NULL, CONSTRAINT "UQ_576678406a479d569123a33e132" UNIQUE ("key", "user_id"), CONSTRAINT "PK_8f8251016cd9283e7eb04c5498b" PRIMARY KEY ("id"))`); + await queryRunner.query(`CREATE INDEX "IDX_673fe530e2484ff7e31ac81099" ON "e_usr_preference_backend" ("key") `); + await queryRunner.query(`CREATE INDEX "IDX_f1a427e855045fa793c275861a" ON "e_usr_preference_backend" ("user_id") `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "public"."IDX_f1a427e855045fa793c275861a"`); + await queryRunner.query(`DROP INDEX "public"."IDX_673fe530e2484ff7e31ac81099"`); + await queryRunner.query(`DROP TABLE "e_usr_preference_backend"`); + await queryRunner.query(`DROP INDEX "public"."IDX_ae538430fd08b28f4ab297eff0"`); + await queryRunner.query(`DROP TABLE "e_user_backend"`); + await queryRunner.query(`DROP INDEX "public"."IDX_b04e47c4814fb6e315c5879fa7"`); + await queryRunner.query(`DROP TABLE "e_sys_preference_backend"`); + await queryRunner.query(`DROP INDEX "public"."IDX_cbedb9f42a98a82d91422e7fed"`); + await queryRunner.query(`DROP TABLE "e_role_backend"`); + await queryRunner.query(`DROP TABLE "e_image_backend"`); + await queryRunner.query(`DROP INDEX "public"."IDX_d0500b00b0b4109b623f897c2d"`); + await queryRunner.query(`DROP INDEX "public"."IDX_8055f37d3b9f52f421b94ee84d"`); + await queryRunner.query(`DROP TABLE "e_image_file_backend"`); + await queryRunner.query(`DROP INDEX "public"."IDX_7dc534a666f442383341896062"`); + await queryRunner.query(`DROP INDEX "public"."IDX_37055605f39b3f8847232d604f"`); + await queryRunner.query(`DROP TABLE "e_image_derivative_backend"`); + } + +} diff --git a/backend/src/database/migrations/index.ts b/backend/src/database/migrations/index.ts new file mode 100644 index 0000000..6ece044 --- /dev/null +++ b/backend/src/database/migrations/index.ts @@ -0,0 +1,3 @@ +import { V030A1661692206479 } from './1661692206479-V_0_3_0_a'; + +export const MigrationList: Function[] = [V030A1661692206479]; diff --git a/backend/src/datasource.ts b/backend/src/datasource.ts new file mode 100644 index 0000000..0740234 --- /dev/null +++ b/backend/src/datasource.ts @@ -0,0 +1,35 @@ +import { NestFactory } from '@nestjs/core'; +import { + FastifyAdapter, NestFastifyApplication +} from '@nestjs/platform-fastify'; +import { DataSource, InstanceChecker } from 'typeorm'; +import { TypeOrmConfigService } from './config/early/type-orm.config.service'; +import { DatabaseModule } from './database/database.module'; + +// TODO, upgrade to a version beyond typeorm 3.8, cause 3.8 is bugged +// So here we monkeypatch 3.7 +function patchAsyncDataSourceSetup() { + const oldIsDataSource = InstanceChecker.isDataSource; + InstanceChecker.isDataSource = function (obj: unknown): obj is DataSource { + if (obj instanceof Promise) { + return true; + } + return oldIsDataSource(obj); + }; +} +patchAsyncDataSourceSetup(); + +async function createDataSource() { + // Create nest app + const app = await NestFactory.create( + DatabaseModule, + new FastifyAdapter(), + ); + + const configFactory = app.get(TypeOrmConfigService); + const config = await configFactory.createTypeOrmOptions(); + + return new DataSource(config); +} + +export default createDataSource().catch(console.error); diff --git a/backend/src/logger/logger.service.ts b/backend/src/logger/logger.service.ts index c513e0d..a4eed84 100644 --- a/backend/src/logger/logger.service.ts +++ b/backend/src/logger/logger.service.ts @@ -5,7 +5,6 @@ import { HostConfigService } from '../config/early/host.config.service'; export class PicsurLoggerService extends ConsoleLogger { constructor(hostService: HostConfigService) { super(); - if (hostService.isProduction()) { super.setLogLevels(['error', 'warn', 'log']); } diff --git a/backend/src/main.ts b/backend/src/main.ts index fcdcfb2..7b18b20 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -1,5 +1,5 @@ import fastifyHelmet from '@fastify/helmet'; -import * as multipart from '@fastify/multipart'; +import multipart from '@fastify/multipart'; import { NestFactory, Reflector } from '@nestjs/core'; import { FastifyAdapter, @@ -31,6 +31,11 @@ async function bootstrap() { }, ); + // Configure logger + app.useLogger(app.get(PicsurLoggerService)); + + app.flushLogs(); + app.useGlobalFilters(new MainExceptionFilter()); app.useGlobalInterceptors(new SuccessInterceptor(app.get(Reflector))); app.useGlobalPipes(new ZodValidationPipe()); @@ -38,9 +43,6 @@ async function bootstrap() { new MainAuthGuard(app.get(Reflector), app.get(UsersService)), ); - // Configure logger - app.useLogger(app.get(PicsurLoggerService)); - // Start app const hostConfigService = app.get(HostConfigService); await app.listen(hostConfigService.getPort(), hostConfigService.getHost()); diff --git a/backend/src/managers/auth/guest.service.ts b/backend/src/managers/auth/guest.service.ts index 60cae4b..2a7266c 100644 --- a/backend/src/managers/auth/guest.service.ts +++ b/backend/src/managers/auth/guest.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { HasFailed } from 'picsur-shared/dist/types'; import { UsersService } from '../../collections/user-db/user-db.service'; -import { EUserBackend } from '../../models/entities/user.entity'; +import { EUserBackend } from '../../database/entities/user.entity'; @Injectable() export class GuestService { diff --git a/backend/src/managers/image/image.service.ts b/backend/src/managers/image/image.service.ts index 47b2550..c2044ec 100644 --- a/backend/src/managers/image/image.service.ts +++ b/backend/src/managers/image/image.service.ts @@ -16,9 +16,9 @@ import { ImageDBService } from '../../collections/image-db/image-db.service'; import { ImageFileDBService } from '../../collections/image-db/image-file-db.service'; import { SysPreferenceService } from '../../collections/preference-db/sys-preference-db.service'; import { UsrPreferenceService } from '../../collections/preference-db/usr-preference-db.service'; -import { EImageDerivativeBackend } from '../../models/entities/image-derivative.entity'; -import { EImageFileBackend } from '../../models/entities/image-file.entity'; -import { EImageBackend } from '../../models/entities/image.entity'; +import { EImageDerivativeBackend } from '../../database/entities/image-derivative.entity'; +import { EImageFileBackend } from '../../database/entities/image-file.entity'; +import { EImageBackend } from '../../database/entities/image.entity'; import { MutexFallBack } from '../../models/util/mutex-fallback'; import { ImageConverterService } from './image-converter.service'; import { ImageProcessorService } from './image-processor.service'; diff --git a/backend/src/models/transformers/user.transformer.ts b/backend/src/models/transformers/user.transformer.ts index 0c0cbac..e16cb55 100644 --- a/backend/src/models/transformers/user.transformer.ts +++ b/backend/src/models/transformers/user.transformer.ts @@ -1,5 +1,5 @@ import { EUser } from 'picsur-shared/dist/entities/user.entity'; -import { EUserBackend } from '../entities/user.entity'; +import { EUserBackend } from '../../database/entities/user.entity'; export function EUserBackend2EUser(eUser: EUserBackend): EUser { if (eUser.hashed_password === undefined) return eUser as EUser; diff --git a/backend/tsconfig.build.json b/backend/tsconfig.build.json deleted file mode 100644 index 8ef5f71..0000000 --- a/backend/tsconfig.build.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": "./tsconfig.json", - "include": ["src/**/*.ts", "src/**/*.d.ts"], - "exclude": ["node_modules", "dist", "test", "**/*spec.ts"] -} diff --git a/backend/tsconfig.json b/backend/tsconfig.json index be576af..6b50c03 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -1,5 +1,7 @@ { "extends": "../tsconfig.base.json", + "include": ["src/**/*.ts", "src/**/*.d.ts"], + "exclude": ["node_modules", "dist", "test", "**/*spec.ts"], "compilerOptions": { "target": "es2020", "module": "es2020", @@ -8,5 +10,8 @@ "declaration": true, "sourceMap": true, "emitDecoratorMetadata": true + }, + "ts-node": { + "experimentalSpecifierResolution": "node" } } diff --git a/frontend/angular.json b/frontend/angular.json index 26c2cce..396bbd2 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -21,7 +21,7 @@ "sourceRoot": "src", "architect": { "build": { - "builder": "@angular-devkit/build-angular:browser", + "builder": "@angular-builders/custom-webpack:browser", "options": { "outputPath": "dist", "index": "src/index.html", @@ -37,15 +37,18 @@ "moment" ], "optimization": true, - "webWorkerTsConfig": "tsconfig.worker.json" + "webWorkerTsConfig": "tsconfig.worker.json", + "customWebpackConfig": { + "path": "./custom-webpack.config.js" + } }, "configurations": { "production": { "budgets": [ { "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" + "maximumWarning": "1500kb", + "maximumError": "2mb" }, { "type": "anyComponentStyle", diff --git a/frontend/custom-webpack.config.js b/frontend/custom-webpack.config.js new file mode 100644 index 0000000..17d153b --- /dev/null +++ b/frontend/custom-webpack.config.js @@ -0,0 +1,7 @@ +import webpack from 'webpack'; + +export default { + plugins: [ + new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/), + ], +}; diff --git a/frontend/package.json b/frontend/package.json index 10ef26a..43e4783 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -5,6 +5,7 @@ "license": "GPL-3.0", "repository": "https://github.com/rubikscraft/Picsur", "author": "Rubikscraft ", + "type": "module", "scripts": { "ng": "ng", "start": "ng serve --host 0.0.0.0", @@ -41,6 +42,7 @@ "zone.js": "~0.11.8" }, "devDependencies": { + "@angular-builders/custom-webpack": "^14.0.1", "@angular-devkit/build-angular": "14.2.0", "@angular/cli": "^14.2.0", "@angular/compiler-cli": "^14.2.0", diff --git a/package.json b/package.json index bb6803b..4a8956a 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "devdb:start": "docker-compose -f ./support/dev.docker-compose.yml up -d", "devdb:stop": "docker-compose -f ./support/dev.docker-compose.yml down", "devdb:restart": "docker-compose -f ./support/dev.docker-compose.yml restart", - "devdb:remove": "docker-compose -f ./support/dev.docker-compose.yml down --rmi all --volumes", + "devdb:remove": "docker-compose -f ./support/dev.docker-compose.yml down --rm all --volumes", "build": "./support/build.sh", "setversion": "./support/setversion.sh", "purge": "rm -rf ./node_modules", @@ -18,7 +18,8 @@ }, "resolutions": { "fastify": "^4.5.2", - "terser": "^5.14.2", + "terser": "5.14.2", + "typeorm": "0.3.7", "fastify-static": "npm:@fastify/static@*", "fastify-formbody": "npm:@fastify/formbody@*", "minimist": "npm:minimist-lite@*" diff --git a/shared/src/dto/api/image.dto.ts b/shared/src/dto/api/image.dto.ts index 9285713..cb66797 100644 --- a/shared/src/dto/api/image.dto.ts +++ b/shared/src/dto/api/image.dto.ts @@ -2,16 +2,9 @@ import { z } from 'zod'; import { EImageSchema } from '../../entities/image.entity'; import { EUserSchema } from '../../entities/user.entity'; import { createZodDto } from '../../util/create-zod-dto'; +import { ParseBool } from '../../util/parse-simple'; import { ImageEntryVariant } from '../image-entry-variant.enum'; -const parseBool = (value: unknown): boolean | null => { - if (value === true || value === 'true' || value === '1' || value === 'yes') - return true; - if (value === false || value === 'false' || value === '0' || value === 'no') - return false; - return null; -}; - export const ImageRequestParamsSchema = z .object({ height: z.preprocess(Number, z.number().int().min(1).max(32767)), @@ -20,11 +13,11 @@ export const ImageRequestParamsSchema = z Number, z.number().int().multipleOf(90).min(0).max(360), ), - flipx: z.preprocess(parseBool, z.boolean()), - flipy: z.preprocess(parseBool, z.boolean()), - greyscale: z.preprocess(parseBool, z.boolean()), - noalpha: z.preprocess(parseBool, z.boolean()), - negative: z.preprocess(parseBool, z.boolean()), + flipx: z.preprocess(ParseBool, z.boolean()), + flipy: z.preprocess(ParseBool, z.boolean()), + greyscale: z.preprocess(ParseBool, z.boolean()), + noalpha: z.preprocess(ParseBool, z.boolean()), + negative: z.preprocess(ParseBool, z.boolean()), quality: z.preprocess(Number, z.number().int().min(1).max(100)), }) .partial(); diff --git a/shared/src/util/parse-simple.ts b/shared/src/util/parse-simple.ts new file mode 100644 index 0000000..01e59eb --- /dev/null +++ b/shared/src/util/parse-simple.ts @@ -0,0 +1,34 @@ +export const ParseBool = ( + value: unknown, + fallback?: T, +): boolean | T => { + if (value === true || value === 'true' || value === '1' || value === 'yes') + return true; + if (value === false || value === 'false' || value === '0' || value === 'no') + return false; + + return fallback === undefined ? (null as T) : fallback; +}; + +export const ParseInt = ( + value: unknown, + fallback?: T, +): number | T => { + if (typeof value === 'number') return value; + if (typeof value === 'boolean') return value ? 1 : 0; + if (typeof value === 'string') { + const parsed = parseInt(value); + if (!isNaN(parsed)) return parsed; + } + return fallback === undefined ? (null as T) : fallback; +}; + +export const ParseString = ( + value: unknown, + fallback?: T, +): string | T => { + if (typeof value === 'string') return value; + if (typeof value === 'boolean') return value ? 'true' : 'false'; + if (typeof value === 'number') return value.toString(); + return fallback === undefined ? (null as T) : fallback; +}; diff --git a/support/build.sh b/support/build.sh index f01baa5..aaffebb 100755 --- a/support/build.sh +++ b/support/build.sh @@ -10,13 +10,18 @@ VERSION=$(cat ../package.json | grep version | head -1 | awk -F: '{ print $2 }' echo "Building version $VERSION" -docker build -t "$PACKAGE_URL:$VERSION" -t "$PACKAGE_URL:latest" -f ./skala.Dockerfile .. +docker build -t "$PACKAGE_URL:$VERSION" -t "$PACKAGE_URL:latest" -f ./picsur.Dockerfile .. echo "Done" -echo "Pushing to registry" +# only push if argument is set to "push" +if [ "$1" == "push" ]; then + echo "Pushing to registry" -docker push "$PACKAGE_URL:$VERSION" -docker push "$PACKAGE_URL:latest" + docker push "$PACKAGE_URL:$VERSION" + docker push "$PACKAGE_URL:latest" -echo "Done" + echo "Done" +else + echo "Not pushing to registry" +fi diff --git a/support/dev.docker-compose.yml b/support/dev.docker-compose.yml index 971a118..50062c9 100644 --- a/support/dev.docker-compose.yml +++ b/support/dev.docker-compose.yml @@ -1,13 +1,11 @@ version: '3' services: devdb: - image: postgres:11-alpine + image: postgres:14-alpine environment: POSTGRES_DB: picsur POSTGRES_PASSWORD: picsur POSTGRES_USER: picsur - logging: - driver: 'none' ports: - '5432:5432' restart: unless-stopped diff --git a/support/picsur.Dockerfile b/support/picsur.Dockerfile index c939ea7..6fd6215 100644 --- a/support/picsur.Dockerfile +++ b/support/picsur.Dockerfile @@ -1,4 +1,4 @@ -FROM node:18.8 +FROM node:18.8-bullseye # Sorry for the humongous docker container this generates # Maybe I'll trim it down some day @@ -8,16 +8,10 @@ ENV PICSUR_PRODUCTION=true ADD . /picsur WORKDIR /picsur -RUN yarn install --frozen-lockfile +RUN yarn install --immutable -WORKDIR /picsur/shared -RUN yarn build - -WORKDIR /picsur/frontend -RUN yarn build - -WORKDIR /picsur/backend -RUN yarn build - -CMD ["yarn", "start:prod"] +RUN yarn workspace picsur-shared build +RUN yarn workspace picsur-frontend build +RUN yarn workspace picsur-backend build +CMD /bin/bash -c "yarn workspace picsur-backend start:prod" diff --git a/support/picsur.docker-compose.yml b/support/picsur.docker-compose.yml index ea16947..23d1392 100644 --- a/support/picsur.docker-compose.yml +++ b/support/picsur.docker-compose.yml @@ -10,10 +10,11 @@ services: # PICSUR_PORT: 8080 PICSUR_DB_HOST: picsur_postgres + # PICSUR_DB_PORT: 5432 - # PICSUR_DB_USER: picsur + # PICSUR_DB_USERNAME: picsur # PICSUR_DB_PASSWORD: picsur - # PICSUR_DB_NAME: picsur + # PICSUR_DB_DATABASE: picsur # PICSUR_ADMIN_PASSWORD: picsur @@ -24,7 +25,7 @@ services: # PICSUR_STATIC_FRONTEND_ROOT: "/picsur/frontend/dist" restart: unless-stopped picsur_postgres: - image: postgres:11-alpine + image: postgres:14-alpine container_name: picsur_postgres environment: POSTGRES_DB: picsur diff --git a/support/purge-all.sh b/support/purge-all.sh index 99c8d95..1c06700 100755 --- a/support/purge-all.sh +++ b/support/purge-all.sh @@ -1,8 +1,8 @@ #!/bin/bash -yarn workspace shared purge -yarn workspace backend purge -yarn workspace frontend purge +yarn workspace picsur-shared purge +yarn workspace picsur-backend purge +yarn workspace picsur-frontend purge -yarn devdb:purge +yarn devdb:remove yarn purge diff --git a/yarn.lock b/yarn.lock index 7f0847e..eeac933 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,6 +22,23 @@ __metadata: languageName: node linkType: hard +"@angular-builders/custom-webpack@npm:^14.0.1": + version: 14.0.1 + resolution: "@angular-builders/custom-webpack@npm:14.0.1" + dependencies: + "@angular-devkit/architect": ">=0.1400.0 < 0.1500.0" + "@angular-devkit/build-angular": ^14.0.0 + "@angular-devkit/core": ^14.0.0 + lodash: ^4.17.15 + ts-node: ^10.0.0 + tsconfig-paths: ^3.9.0 + webpack-merge: ^5.7.3 + peerDependencies: + "@angular/compiler-cli": ^14.0.0 + checksum: 6cae568d4f010588f251a5acb9dbf66584e7850243eba3c5c14059b73b48310d1c98a4e1d8b1789bf6d7c1ab2dcf434d3252fdde6a668670c1730a21c56d4150 + languageName: node + linkType: hard + "@angular-devkit/architect@npm:0.1402.0": version: 0.1402.0 resolution: "@angular-devkit/architect@npm:0.1402.0" @@ -32,6 +49,16 @@ __metadata: languageName: node linkType: hard +"@angular-devkit/architect@npm:0.1402.1, @angular-devkit/architect@npm:>=0.1400.0 < 0.1500.0": + version: 0.1402.1 + resolution: "@angular-devkit/architect@npm:0.1402.1" + dependencies: + "@angular-devkit/core": 14.2.1 + rxjs: 6.6.7 + checksum: 8338710b57ea761695cb77996053d948f76fd2dd4b6a68499a473ad554ec483df1fd2c690c7d2abcf95c60a51f666e15a70cc1e6edd8270104c90a64c57c5ee7 + languageName: node + linkType: hard + "@angular-devkit/build-angular@npm:14.2.0": version: 14.2.0 resolution: "@angular-devkit/build-angular@npm:14.2.0" @@ -128,6 +155,102 @@ __metadata: languageName: node linkType: hard +"@angular-devkit/build-angular@npm:^14.0.0": + version: 14.2.1 + resolution: "@angular-devkit/build-angular@npm:14.2.1" + dependencies: + "@ampproject/remapping": 2.2.0 + "@angular-devkit/architect": 0.1402.1 + "@angular-devkit/build-webpack": 0.1402.1 + "@angular-devkit/core": 14.2.1 + "@babel/core": 7.18.10 + "@babel/generator": 7.18.12 + "@babel/helper-annotate-as-pure": 7.18.6 + "@babel/plugin-proposal-async-generator-functions": 7.18.10 + "@babel/plugin-transform-async-to-generator": 7.18.6 + "@babel/plugin-transform-runtime": 7.18.10 + "@babel/preset-env": 7.18.10 + "@babel/runtime": 7.18.9 + "@babel/template": 7.18.10 + "@discoveryjs/json-ext": 0.5.7 + "@ngtools/webpack": 14.2.1 + ansi-colors: 4.1.3 + babel-loader: 8.2.5 + babel-plugin-istanbul: 6.1.1 + browserslist: ^4.9.1 + cacache: 16.1.2 + copy-webpack-plugin: 11.0.0 + critters: 0.0.16 + css-loader: 6.7.1 + esbuild: 0.15.5 + esbuild-wasm: 0.15.5 + glob: 8.0.3 + https-proxy-agent: 5.0.1 + inquirer: 8.2.4 + jsonc-parser: 3.1.0 + karma-source-map-support: 1.4.0 + less: 4.1.3 + less-loader: 11.0.0 + license-webpack-plugin: 4.0.2 + loader-utils: 3.2.0 + mini-css-extract-plugin: 2.6.1 + minimatch: 5.1.0 + open: 8.4.0 + ora: 5.4.1 + parse5-html-rewriting-stream: 6.0.1 + piscina: 3.2.0 + postcss: 8.4.16 + postcss-import: 14.1.0 + postcss-loader: 7.0.1 + postcss-preset-env: 7.8.0 + regenerator-runtime: 0.13.9 + resolve-url-loader: 5.0.0 + rxjs: 6.6.7 + sass: 1.54.4 + sass-loader: 13.0.2 + semver: 7.3.7 + source-map-loader: 4.0.0 + source-map-support: 0.5.21 + stylus: 0.59.0 + stylus-loader: 7.0.0 + terser: 5.14.2 + text-table: 0.2.0 + tree-kill: 1.2.2 + tslib: 2.4.0 + webpack: 5.74.0 + webpack-dev-middleware: 5.3.3 + webpack-dev-server: 4.10.0 + webpack-merge: 5.8.0 + webpack-subresource-integrity: 5.1.0 + peerDependencies: + "@angular/compiler-cli": ^14.0.0 + "@angular/localize": ^14.0.0 + "@angular/service-worker": ^14.0.0 + karma: ^6.3.0 + ng-packagr: ^14.0.0 + protractor: ^7.0.0 + tailwindcss: ^2.0.0 || ^3.0.0 + typescript: ">=4.6.2 <4.9" + dependenciesMeta: + esbuild: + optional: true + peerDependenciesMeta: + "@angular/localize": + optional: true + "@angular/service-worker": + optional: true + karma: + optional: true + ng-packagr: + optional: true + protractor: + optional: true + tailwindcss: + optional: true + checksum: 6b1fb478fc3ad890f15458f70d30b396e9aaa20ac0e015dc17713bfcc69218b959d03bae711a63ad063b1df34d50cf8f077d32d21d4b1b6f1635415a3734cb92 + languageName: node + linkType: hard + "@angular-devkit/build-webpack@npm:0.1402.0": version: 0.1402.0 resolution: "@angular-devkit/build-webpack@npm:0.1402.0" @@ -141,6 +264,19 @@ __metadata: languageName: node linkType: hard +"@angular-devkit/build-webpack@npm:0.1402.1": + version: 0.1402.1 + resolution: "@angular-devkit/build-webpack@npm:0.1402.1" + dependencies: + "@angular-devkit/architect": 0.1402.1 + rxjs: 6.6.7 + peerDependencies: + webpack: ^5.30.0 + webpack-dev-server: ^4.0.0 + checksum: b57c17b14f85bd48c1ae7637a5d576211dcfab90f4dec068258d95a4b09bc6db88bb02a9c6ad17d257726cd9477839b18537e8a0200d5e2d51f5bd7d60c1ca15 + languageName: node + linkType: hard + "@angular-devkit/core@npm:14.0.5": version: 14.0.5 resolution: "@angular-devkit/core@npm:14.0.5" @@ -177,6 +313,24 @@ __metadata: languageName: node linkType: hard +"@angular-devkit/core@npm:14.2.1, @angular-devkit/core@npm:^14.0.0": + version: 14.2.1 + resolution: "@angular-devkit/core@npm:14.2.1" + dependencies: + ajv: 8.11.0 + ajv-formats: 2.1.1 + jsonc-parser: 3.1.0 + rxjs: 6.6.7 + source-map: 0.7.4 + peerDependencies: + chokidar: ^3.5.2 + peerDependenciesMeta: + chokidar: + optional: true + checksum: 67a4c57a6e51bbb7151fa57d5d27e2360dea55b125343ff79939fc7c15dc88b6d027303f98024c3bef3a994a901212ddb2f3d6fd6f6433760e1b7bb504f0648f + languageName: node + linkType: hard + "@angular-devkit/schematics-cli@npm:14.0.5": version: 14.0.5 resolution: "@angular-devkit/schematics-cli@npm:14.0.5" @@ -2726,6 +2880,17 @@ __metadata: languageName: node linkType: hard +"@ngtools/webpack@npm:14.2.1": + version: 14.2.1 + resolution: "@ngtools/webpack@npm:14.2.1" + peerDependencies: + "@angular/compiler-cli": ^14.0.0 + typescript: ">=4.6.2 <4.9" + webpack: ^5.54.0 + checksum: 6adf3ac922bc411ba82f7ded4c2bcdd2162b72570e78169ee39e694daac6b8c5b1c9968f888de159f534a6269dd787ef4dabd85627f5ac39b0f0a844a7d44487 + languageName: node + linkType: hard + "@ngui/common@npm:^1.0.0": version: 1.0.0 resolution: "@ngui/common@npm:1.0.0" @@ -7504,7 +7669,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:4.17.21, lodash@npm:^4.17.19, lodash@npm:^4.17.21": +"lodash@npm:4.17.21, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -8945,6 +9110,7 @@ __metadata: version: 0.0.0-use.local resolution: "picsur-frontend@workspace:frontend" dependencies: + "@angular-builders/custom-webpack": ^14.0.1 "@angular-devkit/build-angular": 14.2.0 "@angular/animations": ^14.2.0 "@angular/cdk": ^14.2.0 @@ -11060,9 +11226,9 @@ __metadata: languageName: node linkType: hard -"terser@npm:^5.14.2": - version: 5.15.0 - resolution: "terser@npm:5.15.0" +"terser@npm:5.14.2": + version: 5.14.2 + resolution: "terser@npm:5.14.2" dependencies: "@jridgewell/source-map": ^0.3.2 acorn: ^8.5.0 @@ -11070,7 +11236,7 @@ __metadata: source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: b2358c989fcb76b4a1c265f60e175c950d3f776e5f619a9f58f54e8d2d792cd6b4cca86071834075f3b9943556d695357bafdd4ee2390de2fc9fd96ba3efa8c8 + checksum: cabb50a640d6c2cfb351e4f43dc7bf7436f649755bb83eb78b2cacda426d5e0979bd44e6f92d713f3ca0f0866e322739b9ced888ebbce6508ad872d08de74fcc languageName: node linkType: hard @@ -11237,7 +11403,7 @@ __metadata: languageName: node linkType: hard -"ts-node@npm:^10.9.1": +"ts-node@npm:^10.0.0, ts-node@npm:^10.9.1": version: 10.9.1 resolution: "ts-node@npm:10.9.1" dependencies: @@ -11779,7 +11945,7 @@ __metadata: languageName: node linkType: hard -"webpack-merge@npm:5.8.0": +"webpack-merge@npm:5.8.0, webpack-merge@npm:^5.7.3": version: 5.8.0 resolution: "webpack-merge@npm:5.8.0" dependencies: