Activate typescript strict mode for server
Build and publish docker image snapshot / build-and-publish (push) Successful in 1m16s
Details
Build and publish docker image snapshot / build-and-publish (push) Successful in 1m16s
Details
Should have been set from the start
This commit is contained in:
parent
272edc8f20
commit
c6f374de8a
|
|
@ -34,7 +34,7 @@ An easy way to run simple picture gallery is with docker.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker pull docker pull ghcr.io/t-h-e/simple-picture-gallery:latest
|
docker pull docker pull ghcr.io/t-h-e/simple-picture-gallery:latest
|
||||||
docker run -p 3005:3001 -v /mnt/path/to/pictures:/usr/src/app/public --name my-picture-gallery ghcr.io/t-h-e/simple-picture-gallery:latest
|
docker run -d -p 3005:3001 -v /mnt/path/to/pictures:/usr/src/app/public --name my-picture-gallery ghcr.io/t-h-e/simple-picture-gallery:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Customization
|
#### Customization
|
||||||
|
|
@ -44,13 +44,13 @@ Create an environment file `.env` containing any of the following properties to
|
||||||
```properties
|
```properties
|
||||||
VITE_TITLE=My Gallery
|
VITE_TITLE=My Gallery
|
||||||
VITE_APPBAR_COLOR=#F8AB2D
|
VITE_APPBAR_COLOR=#F8AB2D
|
||||||
VITE_FAVICON_HREF=<URL to your favicon>
|
VITE_FAVICON_HREF=<URL to your favicon or remove this property>
|
||||||
```
|
```
|
||||||
|
|
||||||
And run docker with `--env-file .env`
|
And run docker with `--env-file .env`
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker run -p 3005:3001 -v /mnt/path/to/pictures:/usr/src/app/public --env-file .env --name my-picture-gallery ghcr.io/t-h-e/simple-picture-gallery:latest
|
docker run -d -p 3005:3001 -v /mnt/path/to/pictures:/usr/src/app/public --env-file .env --name my-picture-gallery ghcr.io/t-h-e/simple-picture-gallery:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
### Docker Compose
|
### Docker Compose
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,15 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"lib": [
|
"lib": [
|
||||||
"dom",
|
"dom",
|
||||||
"dom.iterable",
|
"dom.iterable",
|
||||||
"esnext"
|
"esnext"
|
||||||
],
|
],
|
||||||
"allowJs": true,
|
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"strict": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
|
|
|
||||||
|
|
@ -38,3 +38,16 @@ export const notEmpty = <TValue>(
|
||||||
): value is TValue => {
|
): value is TValue => {
|
||||||
return value !== null && value !== undefined;
|
return value !== null && value !== undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const definedOrError = <TValue>(
|
||||||
|
value: TValue | void | null | undefined,
|
||||||
|
): TValue => {
|
||||||
|
if (notEmpty(value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
throw Error("Value was not defined.");
|
||||||
|
};
|
||||||
|
|
||||||
|
export const definedOrZero = (
|
||||||
|
value: number | void | null | undefined,
|
||||||
|
): number => (notEmpty(value) ? value : 0);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import express from "express";
|
||||||
import { a, FolderPreview, Folders, Image } from "../models";
|
import { a, FolderPreview, Folders, Image } from "../models";
|
||||||
import { publicPath, thumbnailPath, thumbnailPublicPath } from "../paths";
|
import { publicPath, thumbnailPath, thumbnailPublicPath } from "../paths";
|
||||||
import { securityValidation } from "./securityChecks";
|
import { securityValidation } from "./securityChecks";
|
||||||
import { getRequestedPath, notEmpty } from "./common";
|
import { definedOrError, getRequestedPath, notEmpty } from "./common";
|
||||||
import { consoleLogger } from "../logging";
|
import { consoleLogger } from "../logging";
|
||||||
import { getImage } from "./images";
|
import { getImage } from "./images";
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ const getFirstImageInFolder = async (
|
||||||
): Promise<Image | void> => {
|
): Promise<Image | void> => {
|
||||||
const dirs = [dirPath];
|
const dirs = [dirPath];
|
||||||
while (dirs.length > 0) {
|
while (dirs.length > 0) {
|
||||||
const curPath = dirs.shift();
|
const curPath = definedOrError(dirs.shift());
|
||||||
const dirContent = fs.readdirSync(path.posix.join(publicPath, curPath), {
|
const dirContent = fs.readdirSync(path.posix.join(publicPath, curPath), {
|
||||||
withFileTypes: true,
|
withFileTypes: true,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { a, Folder, Image } from "../models";
|
||||||
import { consoleLogger } from "../logging";
|
import { consoleLogger } from "../logging";
|
||||||
import { securityValidation } from "./securityChecks";
|
import { securityValidation } from "./securityChecks";
|
||||||
import {
|
import {
|
||||||
|
definedOrZero,
|
||||||
getRequestedPath,
|
getRequestedPath,
|
||||||
getSrc,
|
getSrc,
|
||||||
getThumbnail,
|
getThumbnail,
|
||||||
|
|
@ -21,12 +22,15 @@ const toImage = (
|
||||||
f: Dirent,
|
f: Dirent,
|
||||||
thumbnailExists: boolean,
|
thumbnailExists: boolean,
|
||||||
): Image => {
|
): Image => {
|
||||||
const widthAndHeightSwap = metadata.orientation > 4; // see https://exiftool.org/TagNames/EXIF.html
|
const widthAndHeightSwap =
|
||||||
|
metadata.orientation !== undefined && metadata.orientation > 4; // see https://exiftool.org/TagNames/EXIF.html
|
||||||
return a<Image>({
|
return a<Image>({
|
||||||
src: getSrc(filePath, f),
|
src: getSrc(filePath, f),
|
||||||
thumbnail: getThumbnail(filePath, f, thumbnailExists),
|
thumbnail: getThumbnail(filePath, f, thumbnailExists),
|
||||||
width: widthAndHeightSwap ? metadata.height : metadata.width,
|
width: definedOrZero(widthAndHeightSwap ? metadata.height : metadata.width),
|
||||||
height: widthAndHeightSwap ? metadata.width : metadata.height,
|
height: definedOrZero(
|
||||||
|
widthAndHeightSwap ? metadata.width : metadata.height,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ export const createThumbnailAsyncForImage = (image: string) => {
|
||||||
sharp(publicImagePath)
|
sharp(publicImagePath)
|
||||||
.metadata()
|
.metadata()
|
||||||
.then((info) => {
|
.then((info) => {
|
||||||
|
if (info.width === undefined || info.height === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const width = Math.max(
|
const width = Math.max(
|
||||||
Math.min(info.width, minimumPixelForThumbnail),
|
Math.min(info.width, minimumPixelForThumbnail),
|
||||||
Math.round((info.width * percentage) / 100),
|
Math.round((info.width * percentage) / 100),
|
||||||
|
|
@ -25,6 +28,9 @@ export const createThumbnailAsyncForImage = (image: string) => {
|
||||||
path.posix.join(thumbnailPublicPath, path.dirname(image)),
|
path.posix.join(thumbnailPublicPath, path.dirname(image)),
|
||||||
{ recursive: true },
|
{ recursive: true },
|
||||||
() => {
|
() => {
|
||||||
|
if (info.width === undefined || info.height === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
sharp(publicImagePath)
|
sharp(publicImagePath)
|
||||||
.withMetadata()
|
.withMetadata()
|
||||||
.resize(info.width > info.height ? { width } : { height })
|
.resize(info.width > info.height ? { width } : { height })
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue