mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
chore: organize config, validation, decorators (#8118)
* refactor: validation * refactor: utilities * refactor: config
This commit is contained in:
parent
92cc647cf6
commit
81f0265095
119 changed files with 666 additions and 684 deletions
|
|
@ -1,16 +1,7 @@
|
|||
import _ from 'lodash';
|
||||
import {
|
||||
Paginated,
|
||||
PaginatedBuilderOptions,
|
||||
PaginationMode,
|
||||
PaginationOptions,
|
||||
PaginationResult,
|
||||
chunks,
|
||||
setUnion,
|
||||
} from 'src/domain/domain.util';
|
||||
import { AssetSearchBuilderOptions } from 'src/domain/repositories/search.repository';
|
||||
import { AssetEntity } from 'src/infra/entities/asset.entity';
|
||||
import { DATABASE_PARAMETER_CHUNK_SIZE } from 'src/infra/infra.util';
|
||||
import { Paginated, PaginatedBuilderOptions, PaginationMode, PaginationOptions, PaginationResult } from 'src/utils';
|
||||
import {
|
||||
Between,
|
||||
FindManyOptions,
|
||||
|
|
@ -37,11 +28,6 @@ export function OptionalBetween<T>(from?: T, to?: T) {
|
|||
}
|
||||
}
|
||||
|
||||
export const isValidInteger = (value: number, options: { min?: number; max?: number }): value is number => {
|
||||
const { min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER } = options;
|
||||
return Number.isInteger(value) && value >= min && value <= max;
|
||||
};
|
||||
|
||||
function paginationHelper<Entity extends ObjectLiteral>(items: Entity[], take: number): PaginationResult<Entity> {
|
||||
const hasNextPage = items.length > take;
|
||||
items.splice(take);
|
||||
|
|
@ -86,70 +72,6 @@ export async function paginatedBuilder<Entity extends ObjectLiteral>(
|
|||
export const asVector = (embedding: number[], quote = false) =>
|
||||
quote ? `'[${embedding.join(',')}]'` : `[${embedding.join(',')}]`;
|
||||
|
||||
/**
|
||||
* Wraps a method that takes a collection of parameters and sequentially calls it with chunks of the collection,
|
||||
* to overcome the maximum number of parameters allowed by the database driver.
|
||||
*
|
||||
* @param options.paramIndex The index of the function parameter to chunk. Defaults to 0.
|
||||
* @param options.flatten Whether to flatten the results. Defaults to false.
|
||||
*/
|
||||
export function Chunked(options: { paramIndex?: number; mergeFn?: (results: any) => any } = {}): MethodDecorator {
|
||||
return (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
|
||||
const originalMethod = descriptor.value;
|
||||
const parameterIndex = options.paramIndex ?? 0;
|
||||
descriptor.value = async function (...arguments_: any[]) {
|
||||
const argument = arguments_[parameterIndex];
|
||||
|
||||
// Early return if argument length is less than or equal to the chunk size.
|
||||
if (
|
||||
(Array.isArray(argument) && argument.length <= DATABASE_PARAMETER_CHUNK_SIZE) ||
|
||||
(argument instanceof Set && argument.size <= DATABASE_PARAMETER_CHUNK_SIZE)
|
||||
) {
|
||||
return await originalMethod.apply(this, arguments_);
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
chunks(argument, DATABASE_PARAMETER_CHUNK_SIZE).map(async (chunk) => {
|
||||
await Reflect.apply(originalMethod, this, [
|
||||
...arguments_.slice(0, parameterIndex),
|
||||
chunk,
|
||||
...arguments_.slice(parameterIndex + 1),
|
||||
]);
|
||||
}),
|
||||
).then((results) => (options.mergeFn ? options.mergeFn(results) : results));
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function ChunkedArray(options?: { paramIndex?: number }): MethodDecorator {
|
||||
return Chunked({ ...options, mergeFn: _.flatten });
|
||||
}
|
||||
|
||||
export function ChunkedSet(options?: { paramIndex?: number }): MethodDecorator {
|
||||
return Chunked({ ...options, mergeFn: setUnion });
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/74898678
|
||||
export function DecorateAll(
|
||||
decorator: <T>(
|
||||
target: any,
|
||||
propertyKey: string,
|
||||
descriptor: TypedPropertyDescriptor<T>,
|
||||
) => TypedPropertyDescriptor<T> | void,
|
||||
) {
|
||||
return (target: any) => {
|
||||
const descriptors = Object.getOwnPropertyDescriptors(target.prototype);
|
||||
for (const [propName, descriptor] of Object.entries(descriptors)) {
|
||||
const isMethod = typeof descriptor.value == 'function' && propName !== 'constructor';
|
||||
if (!isMethod) {
|
||||
continue;
|
||||
}
|
||||
decorator({ ...target, constructor: { ...target.constructor, name: target.name } as any }, propName, descriptor);
|
||||
Object.defineProperty(target.prototype, propName, descriptor);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function searchAssetBuilder(
|
||||
builder: SelectQueryBuilder<AssetEntity>,
|
||||
options: AssetSearchBuilderOptions,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue