mirror of
https://github.com/immich-app/immich.git
synced 2026-03-01 18:19:10 +03:00
refactor: enum casing (#19946)
This commit is contained in:
@@ -91,7 +91,7 @@ class AlbumAccess {
|
||||
}
|
||||
|
||||
const accessRole =
|
||||
access === AlbumUserRole.EDITOR ? [AlbumUserRole.EDITOR] : [AlbumUserRole.EDITOR, AlbumUserRole.VIEWER];
|
||||
access === AlbumUserRole.Editor ? [AlbumUserRole.Editor] : [AlbumUserRole.Editor, AlbumUserRole.Viewer];
|
||||
|
||||
return this.db
|
||||
.selectFrom('album')
|
||||
@@ -178,7 +178,7 @@ class AssetAccess {
|
||||
.select('asset.id')
|
||||
.where('asset.id', 'in', [...assetIds])
|
||||
.where('asset.ownerId', '=', userId)
|
||||
.$if(!hasElevatedPermission, (eb) => eb.where('asset.visibility', '!=', AssetVisibility.LOCKED))
|
||||
.$if(!hasElevatedPermission, (eb) => eb.where('asset.visibility', '!=', AssetVisibility.Locked))
|
||||
.execute()
|
||||
.then((assets) => new Set(assets.map((asset) => asset.id)));
|
||||
}
|
||||
@@ -200,8 +200,8 @@ class AssetAccess {
|
||||
.where('partner.sharedWithId', '=', userId)
|
||||
.where((eb) =>
|
||||
eb.or([
|
||||
eb('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE)),
|
||||
eb('asset.visibility', '=', sql.lit(AssetVisibility.HIDDEN)),
|
||||
eb('asset.visibility', '=', sql.lit(AssetVisibility.Timeline)),
|
||||
eb('asset.visibility', '=', sql.lit(AssetVisibility.Hidden)),
|
||||
]),
|
||||
)
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ export class ActivityRepository {
|
||||
.where('activity.albumId', '=', albumId)
|
||||
.where(({ or, and, eb }) =>
|
||||
or([
|
||||
and([eb('asset.deletedAt', 'is', null), eb('asset.visibility', '!=', sql.lit(AssetVisibility.LOCKED))]),
|
||||
and([eb('asset.deletedAt', 'is', null), eb('asset.visibility', '!=', sql.lit(AssetVisibility.Locked))]),
|
||||
eb('asset.id', 'is', null),
|
||||
]),
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ export class AlbumUserRepository {
|
||||
.executeTakeFirstOrThrow();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }, { role: AlbumUserRole.VIEWER }] })
|
||||
@GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }, { role: AlbumUserRole.Viewer }] })
|
||||
update({ usersId, albumsId }: AlbumPermissionId, dto: Updateable<AlbumUserTable>) {
|
||||
return this.db
|
||||
.updateTable('album_user')
|
||||
|
||||
@@ -62,7 +62,7 @@ export class AssetJobRepository {
|
||||
.select(['asset.id', 'asset.thumbhash'])
|
||||
.select(withFiles)
|
||||
.where('asset.deletedAt', 'is', null)
|
||||
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
|
||||
.where('asset.visibility', '!=', AssetVisibility.Hidden)
|
||||
.$if(!force, (qb) =>
|
||||
qb
|
||||
// If there aren't any entries, metadata extraction hasn't run yet which is required for thumbnails
|
||||
@@ -117,7 +117,7 @@ export class AssetJobRepository {
|
||||
.executeTakeFirst();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, AssetFileType.THUMBNAIL] })
|
||||
@GenerateSql({ params: [DummyValue.UUID, AssetFileType.Thumbnail] })
|
||||
getAlbumThumbnailFiles(id: string, fileType?: AssetFileType) {
|
||||
return this.db
|
||||
.selectFrom('asset_file')
|
||||
@@ -130,7 +130,7 @@ export class AssetJobRepository {
|
||||
private assetsWithPreviews() {
|
||||
return this.db
|
||||
.selectFrom('asset')
|
||||
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
|
||||
.where('asset.visibility', '!=', AssetVisibility.Hidden)
|
||||
.where('asset.deletedAt', 'is', null)
|
||||
.innerJoin('asset_job_status as job_status', 'assetId', 'asset.id')
|
||||
.where('job_status.previewAt', 'is not', null);
|
||||
@@ -167,7 +167,7 @@ export class AssetJobRepository {
|
||||
return this.db
|
||||
.selectFrom('asset')
|
||||
.select(['asset.id', 'asset.visibility'])
|
||||
.select((eb) => withFiles(eb, AssetFileType.PREVIEW))
|
||||
.select((eb) => withFiles(eb, AssetFileType.Preview))
|
||||
.where('asset.id', '=', id)
|
||||
.executeTakeFirst();
|
||||
}
|
||||
@@ -179,7 +179,7 @@ export class AssetJobRepository {
|
||||
.select(['asset.id', 'asset.visibility'])
|
||||
.$call(withExifInner)
|
||||
.select((eb) => withFaces(eb, true))
|
||||
.select((eb) => withFiles(eb, AssetFileType.PREVIEW))
|
||||
.select((eb) => withFiles(eb, AssetFileType.Preview))
|
||||
.where('asset.id', '=', id)
|
||||
.executeTakeFirst();
|
||||
}
|
||||
@@ -225,7 +225,7 @@ export class AssetJobRepository {
|
||||
.select(['stack.id', 'stack.primaryAssetId'])
|
||||
.select((eb) => eb.fn<Asset[]>('array_agg', [eb.table('stacked')]).as('assets'))
|
||||
.where('stacked.deletedAt', 'is not', null)
|
||||
.where('stacked.visibility', '=', AssetVisibility.TIMELINE)
|
||||
.where('stacked.visibility', '=', AssetVisibility.Timeline)
|
||||
.whereRef('stacked.stackId', '=', 'stack.id')
|
||||
.groupBy('stack.id')
|
||||
.as('stacked_assets'),
|
||||
@@ -241,11 +241,11 @@ export class AssetJobRepository {
|
||||
return this.db
|
||||
.selectFrom('asset')
|
||||
.select(['asset.id'])
|
||||
.where('asset.type', '=', AssetType.VIDEO)
|
||||
.where('asset.type', '=', AssetType.Video)
|
||||
.$if(!force, (qb) =>
|
||||
qb
|
||||
.where((eb) => eb.or([eb('asset.encodedVideoPath', 'is', null), eb('asset.encodedVideoPath', '=', '')]))
|
||||
.where('asset.visibility', '!=', AssetVisibility.HIDDEN),
|
||||
.where('asset.visibility', '!=', AssetVisibility.Hidden),
|
||||
)
|
||||
.where('asset.deletedAt', 'is', null)
|
||||
.stream();
|
||||
@@ -257,7 +257,7 @@ export class AssetJobRepository {
|
||||
.selectFrom('asset')
|
||||
.select(['asset.id', 'asset.ownerId', 'asset.originalPath', 'asset.encodedVideoPath'])
|
||||
.where('asset.id', '=', id)
|
||||
.where('asset.type', '=', AssetType.VIDEO)
|
||||
.where('asset.type', '=', AssetType.Video)
|
||||
.executeTakeFirst();
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ export class AssetJobRepository {
|
||||
.$if(!force, (qb) =>
|
||||
qb.where((eb) => eb.or([eb('asset.sidecarPath', '=', ''), eb('asset.sidecarPath', 'is', null)])),
|
||||
)
|
||||
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
|
||||
.where('asset.visibility', '!=', AssetVisibility.Hidden)
|
||||
.stream();
|
||||
}
|
||||
|
||||
|
||||
@@ -230,13 +230,13 @@ export class AssetRepository {
|
||||
.where('asset_job_status.previewAt', 'is not', null)
|
||||
.where(sql`(asset."localDateTime" at time zone 'UTC')::date`, '=', sql`today.date`)
|
||||
.where('asset.ownerId', '=', anyUuid(ownerIds))
|
||||
.where('asset.visibility', '=', AssetVisibility.TIMELINE)
|
||||
.where('asset.visibility', '=', AssetVisibility.Timeline)
|
||||
.where((eb) =>
|
||||
eb.exists((qb) =>
|
||||
qb
|
||||
.selectFrom('asset_file')
|
||||
.whereRef('assetId', '=', 'asset.id')
|
||||
.where('asset_file.type', '=', AssetFileType.PREVIEW),
|
||||
.where('asset_file.type', '=', AssetFileType.Preview),
|
||||
),
|
||||
)
|
||||
.where('asset.deletedAt', 'is', null)
|
||||
@@ -318,7 +318,7 @@ export class AssetRepository {
|
||||
.select(['deviceAssetId'])
|
||||
.where('ownerId', '=', asUuid(ownerId))
|
||||
.where('deviceId', '=', deviceId)
|
||||
.where('visibility', '!=', AssetVisibility.HIDDEN)
|
||||
.where('visibility', '!=', AssetVisibility.Hidden)
|
||||
.where('deletedAt', 'is', null)
|
||||
.execute();
|
||||
|
||||
@@ -363,7 +363,7 @@ export class AssetRepository {
|
||||
.whereRef('stacked.stackId', '=', 'stack.id')
|
||||
.whereRef('stacked.id', '!=', 'stack.primaryAssetId')
|
||||
.where('stacked.deletedAt', 'is', null)
|
||||
.where('stacked.visibility', '=', AssetVisibility.TIMELINE)
|
||||
.where('stacked.visibility', '=', AssetVisibility.Timeline)
|
||||
.groupBy('stack.id')
|
||||
.as('stacked_assets'),
|
||||
(join) => join.on('stack.id', 'is not', null),
|
||||
@@ -463,15 +463,15 @@ export class AssetRepository {
|
||||
getStatistics(ownerId: string, { visibility, isFavorite, isTrashed }: AssetStatsOptions): Promise<AssetStats> {
|
||||
return this.db
|
||||
.selectFrom('asset')
|
||||
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.AUDIO).as(AssetType.AUDIO))
|
||||
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.IMAGE).as(AssetType.IMAGE))
|
||||
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.VIDEO).as(AssetType.VIDEO))
|
||||
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.OTHER).as(AssetType.OTHER))
|
||||
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.Audio).as(AssetType.Audio))
|
||||
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.Image).as(AssetType.Image))
|
||||
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.Video).as(AssetType.Video))
|
||||
.select((eb) => eb.fn.countAll<number>().filterWhere('type', '=', AssetType.Other).as(AssetType.Other))
|
||||
.where('ownerId', '=', asUuid(ownerId))
|
||||
.$if(visibility === undefined, withDefaultVisibility)
|
||||
.$if(!!visibility, (qb) => qb.where('asset.visibility', '=', visibility!))
|
||||
.$if(isFavorite !== undefined, (qb) => qb.where('isFavorite', '=', isFavorite!))
|
||||
.$if(!!isTrashed, (qb) => qb.where('asset.status', '!=', AssetStatus.DELETED))
|
||||
.$if(!!isTrashed, (qb) => qb.where('asset.status', '!=', AssetStatus.Deleted))
|
||||
.where('deletedAt', isTrashed ? 'is not' : 'is', null)
|
||||
.executeTakeFirstOrThrow();
|
||||
}
|
||||
@@ -496,7 +496,7 @@ export class AssetRepository {
|
||||
qb
|
||||
.selectFrom('asset')
|
||||
.select(truncatedDate<Date>().as('timeBucket'))
|
||||
.$if(!!options.isTrashed, (qb) => qb.where('asset.status', '!=', AssetStatus.DELETED))
|
||||
.$if(!!options.isTrashed, (qb) => qb.where('asset.status', '!=', AssetStatus.Deleted))
|
||||
.where('asset.deletedAt', options.isTrashed ? 'is not' : 'is', null)
|
||||
.$if(options.visibility === undefined, withDefaultVisibility)
|
||||
.$if(!!options.visibility, (qb) => qb.where('asset.visibility', '=', options.visibility!))
|
||||
@@ -606,7 +606,7 @@ export class AssetRepository {
|
||||
.select(sql`array[stacked."stackId"::text, count('stacked')::text]`.as('stack'))
|
||||
.whereRef('stacked.stackId', '=', 'asset.stackId')
|
||||
.where('stacked.deletedAt', 'is', null)
|
||||
.where('stacked.visibility', '=', AssetVisibility.TIMELINE)
|
||||
.where('stacked.visibility', '=', AssetVisibility.Timeline)
|
||||
.groupBy('stacked.stackId')
|
||||
.as('stacked_assets'),
|
||||
(join) => join.onTrue(),
|
||||
@@ -617,7 +617,7 @@ export class AssetRepository {
|
||||
.$if(options.isDuplicate !== undefined, (qb) =>
|
||||
qb.where('asset.duplicateId', options.isDuplicate ? 'is not' : 'is', null),
|
||||
)
|
||||
.$if(!!options.isTrashed, (qb) => qb.where('asset.status', '!=', AssetStatus.DELETED))
|
||||
.$if(!!options.isTrashed, (qb) => qb.where('asset.status', '!=', AssetStatus.Deleted))
|
||||
.$if(!!options.tagId, (qb) => withTagId(qb, options.tagId!))
|
||||
.orderBy('asset.fileCreatedAt', options.order ?? 'desc'),
|
||||
)
|
||||
@@ -671,8 +671,8 @@ export class AssetRepository {
|
||||
.select(['assetId as data', 'asset_exif.city as value'])
|
||||
.$narrowType<{ value: NotNull }>()
|
||||
.where('ownerId', '=', asUuid(ownerId))
|
||||
.where('visibility', '=', AssetVisibility.TIMELINE)
|
||||
.where('type', '=', AssetType.IMAGE)
|
||||
.where('visibility', '=', AssetVisibility.Timeline)
|
||||
.where('type', '=', AssetType.Image)
|
||||
.where('deletedAt', 'is', null)
|
||||
.limit(maxFields)
|
||||
.execute();
|
||||
@@ -710,7 +710,7 @@ export class AssetRepository {
|
||||
)
|
||||
.select((eb) => eb.fn.toJson(eb.table('stacked_assets')).$castTo<Stack | null>().as('stack'))
|
||||
.where('asset.ownerId', '=', asUuid(ownerId))
|
||||
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
|
||||
.where('asset.visibility', '!=', AssetVisibility.Hidden)
|
||||
.where('asset.updatedAt', '<=', updatedUntil)
|
||||
.$if(!!lastId, (qb) => qb.where('asset.id', '>', lastId!))
|
||||
.orderBy('asset.id')
|
||||
@@ -738,7 +738,7 @@ export class AssetRepository {
|
||||
)
|
||||
.select((eb) => eb.fn.toJson(eb.table('stacked_assets').$castTo<Stack | null>()).as('stack'))
|
||||
.where('asset.ownerId', '=', anyUuid(options.userIds))
|
||||
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
|
||||
.where('asset.visibility', '!=', AssetVisibility.Hidden)
|
||||
.where('asset.updatedAt', '>', options.updatedAfter)
|
||||
.limit(options.limit)
|
||||
.execute();
|
||||
|
||||
@@ -18,7 +18,7 @@ export class AuditRepository {
|
||||
@GenerateSql({
|
||||
params: [
|
||||
DummyValue.DATE,
|
||||
{ action: DatabaseAction.CREATE, entityType: EntityType.ASSET, userIds: [DummyValue.UUID] },
|
||||
{ action: DatabaseAction.Create, entityType: EntityType.Asset, userIds: [DummyValue.UUID] },
|
||||
],
|
||||
})
|
||||
async getAfter(since: Date, options: AuditSearch): Promise<string[]> {
|
||||
|
||||
@@ -275,14 +275,14 @@ describe('getEnv', () => {
|
||||
process.env.IMMICH_TELEMETRY_EXCLUDE = 'job';
|
||||
const { telemetry } = getEnv();
|
||||
expect(telemetry.metrics).toEqual(
|
||||
new Set([ImmichTelemetry.API, ImmichTelemetry.HOST, ImmichTelemetry.IO, ImmichTelemetry.REPO]),
|
||||
new Set([ImmichTelemetry.Api, ImmichTelemetry.Host, ImmichTelemetry.Io, ImmichTelemetry.Repo]),
|
||||
);
|
||||
});
|
||||
|
||||
it('should run with specific telemetry metrics', () => {
|
||||
process.env.IMMICH_TELEMETRY_INCLUDE = 'io, host, api';
|
||||
const { telemetry } = getEnv();
|
||||
expect(telemetry.metrics).toEqual(new Set([ImmichTelemetry.API, ImmichTelemetry.HOST, ImmichTelemetry.IO]));
|
||||
expect(telemetry.metrics).toEqual(new Set([ImmichTelemetry.Api, ImmichTelemetry.Host, ImmichTelemetry.Io]));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -136,7 +136,7 @@ const getEnv = (): EnvData => {
|
||||
);
|
||||
}
|
||||
|
||||
const includedWorkers = asSet(dto.IMMICH_WORKERS_INCLUDE, [ImmichWorker.API, ImmichWorker.MICROSERVICES]);
|
||||
const includedWorkers = asSet(dto.IMMICH_WORKERS_INCLUDE, [ImmichWorker.Api, ImmichWorker.Microservices]);
|
||||
const excludedWorkers = asSet(dto.IMMICH_WORKERS_EXCLUDE, []);
|
||||
const workers = [...setDifference(includedWorkers, excludedWorkers)];
|
||||
for (const worker of workers) {
|
||||
@@ -145,8 +145,8 @@ const getEnv = (): EnvData => {
|
||||
}
|
||||
}
|
||||
|
||||
const environment = dto.IMMICH_ENV || ImmichEnvironment.PRODUCTION;
|
||||
const isProd = environment === ImmichEnvironment.PRODUCTION;
|
||||
const environment = dto.IMMICH_ENV || ImmichEnvironment.Production;
|
||||
const isProd = environment === ImmichEnvironment.Production;
|
||||
const buildFolder = dto.IMMICH_BUILD_DATA || '/build';
|
||||
const folders = {
|
||||
geodata: join(buildFolder, 'geodata'),
|
||||
@@ -199,15 +199,15 @@ const getEnv = (): EnvData => {
|
||||
let vectorExtension: VectorExtension | undefined;
|
||||
switch (dto.DB_VECTOR_EXTENSION) {
|
||||
case 'pgvector': {
|
||||
vectorExtension = DatabaseExtension.VECTOR;
|
||||
vectorExtension = DatabaseExtension.Vector;
|
||||
break;
|
||||
}
|
||||
case 'pgvecto.rs': {
|
||||
vectorExtension = DatabaseExtension.VECTORS;
|
||||
vectorExtension = DatabaseExtension.Vectors;
|
||||
break;
|
||||
}
|
||||
case 'vectorchord': {
|
||||
vectorExtension = DatabaseExtension.VECTORCHORD;
|
||||
vectorExtension = DatabaseExtension.VectorChord;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -254,11 +254,11 @@ const getEnv = (): EnvData => {
|
||||
mount: true,
|
||||
generateId: true,
|
||||
setup: (cls, req: Request, res: Response) => {
|
||||
const headerValues = req.headers[ImmichHeader.CID];
|
||||
const headerValues = req.headers[ImmichHeader.Cid];
|
||||
const headerValue = Array.isArray(headerValues) ? headerValues[0] : headerValues;
|
||||
const cid = headerValue || cls.get(CLS_ID);
|
||||
cls.set(CLS_ID, cid);
|
||||
res.header(ImmichHeader.CID, cid);
|
||||
res.header(ImmichHeader.Cid, cid);
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -278,9 +278,9 @@ const getEnv = (): EnvData => {
|
||||
|
||||
otel: {
|
||||
metrics: {
|
||||
hostMetrics: telemetries.has(ImmichTelemetry.HOST),
|
||||
hostMetrics: telemetries.has(ImmichTelemetry.Host),
|
||||
apiMetrics: {
|
||||
enable: telemetries.has(ImmichTelemetry.API),
|
||||
enable: telemetries.has(ImmichTelemetry.Api),
|
||||
ignoreRoutes: excludePaths,
|
||||
},
|
||||
},
|
||||
@@ -335,7 +335,7 @@ export class ConfigRepository {
|
||||
}
|
||||
|
||||
isDev() {
|
||||
return this.getEnv().environment === ImmichEnvironment.DEVELOPMENT;
|
||||
return this.getEnv().environment === ImmichEnvironment.Development;
|
||||
}
|
||||
|
||||
getWorker() {
|
||||
|
||||
@@ -53,8 +53,8 @@ export async function getVectorExtension(runner: Kysely<DB> | QueryRunner): Prom
|
||||
}
|
||||
|
||||
export const probes: Record<VectorIndex, number> = {
|
||||
[VectorIndex.CLIP]: 1,
|
||||
[VectorIndex.FACE]: 1,
|
||||
[VectorIndex.Clip]: 1,
|
||||
[VectorIndex.Face]: 1,
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
@@ -77,7 +77,7 @@ export class DatabaseRepository {
|
||||
return getVectorExtension(this.db);
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [[DatabaseExtension.VECTORS]] })
|
||||
@GenerateSql({ params: [[DatabaseExtension.Vectors]] })
|
||||
async getExtensionVersions(extensions: readonly DatabaseExtension[]): Promise<ExtensionVersion[]> {
|
||||
const { rows } = await sql<ExtensionVersion>`
|
||||
SELECT name, default_version as "availableVersion", installed_version as "installedVersion"
|
||||
@@ -89,13 +89,13 @@ export class DatabaseRepository {
|
||||
|
||||
getExtensionVersionRange(extension: VectorExtension): string {
|
||||
switch (extension) {
|
||||
case DatabaseExtension.VECTORCHORD: {
|
||||
case DatabaseExtension.VectorChord: {
|
||||
return VECTORCHORD_VERSION_RANGE;
|
||||
}
|
||||
case DatabaseExtension.VECTORS: {
|
||||
case DatabaseExtension.Vectors: {
|
||||
return VECTORS_VERSION_RANGE;
|
||||
}
|
||||
case DatabaseExtension.VECTOR: {
|
||||
case DatabaseExtension.Vector: {
|
||||
return VECTOR_VERSION_RANGE;
|
||||
}
|
||||
default: {
|
||||
@@ -117,7 +117,7 @@ export class DatabaseRepository {
|
||||
async createExtension(extension: DatabaseExtension): Promise<void> {
|
||||
this.logger.log(`Creating ${EXTENSION_NAMES[extension]} extension`);
|
||||
await sql`CREATE EXTENSION IF NOT EXISTS ${sql.raw(extension)} CASCADE`.execute(this.db);
|
||||
if (extension === DatabaseExtension.VECTORCHORD) {
|
||||
if (extension === DatabaseExtension.VectorChord) {
|
||||
const dbName = sql.id(await this.getDatabaseName());
|
||||
await sql`ALTER DATABASE ${dbName} SET vchordrq.probes = 1`.execute(this.db);
|
||||
await sql`SET vchordrq.probes = 1`.execute(this.db);
|
||||
@@ -147,8 +147,8 @@ export class DatabaseRepository {
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
this.db.schema.dropIndex(VectorIndex.CLIP).ifExists().execute(),
|
||||
this.db.schema.dropIndex(VectorIndex.FACE).ifExists().execute(),
|
||||
this.db.schema.dropIndex(VectorIndex.Clip).ifExists().execute(),
|
||||
this.db.schema.dropIndex(VectorIndex.Face).ifExists().execute(),
|
||||
]);
|
||||
|
||||
await this.db.transaction().execute(async (tx) => {
|
||||
@@ -156,14 +156,14 @@ export class DatabaseRepository {
|
||||
|
||||
await sql`ALTER EXTENSION ${sql.raw(extension)} UPDATE TO ${sql.lit(targetVersion)}`.execute(tx);
|
||||
|
||||
if (extension === DatabaseExtension.VECTORS && (diff === 'major' || diff === 'minor')) {
|
||||
if (extension === DatabaseExtension.Vectors && (diff === 'major' || diff === 'minor')) {
|
||||
await sql`SELECT pgvectors_upgrade()`.execute(tx);
|
||||
restartRequired = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!restartRequired) {
|
||||
await Promise.all([this.reindexVectors(VectorIndex.CLIP), this.reindexVectors(VectorIndex.FACE)]);
|
||||
await Promise.all([this.reindexVectors(VectorIndex.Clip), this.reindexVectors(VectorIndex.Face)]);
|
||||
}
|
||||
|
||||
return { restartRequired };
|
||||
@@ -171,7 +171,7 @@ export class DatabaseRepository {
|
||||
|
||||
async prewarm(index: VectorIndex): Promise<void> {
|
||||
const vectorExtension = await getVectorExtension(this.db);
|
||||
if (vectorExtension !== DatabaseExtension.VECTORCHORD) {
|
||||
if (vectorExtension !== DatabaseExtension.VectorChord) {
|
||||
return;
|
||||
}
|
||||
this.logger.debug(`Prewarming ${index}`);
|
||||
@@ -196,19 +196,19 @@ export class DatabaseRepository {
|
||||
}
|
||||
|
||||
switch (vectorExtension) {
|
||||
case DatabaseExtension.VECTOR: {
|
||||
case DatabaseExtension.Vector: {
|
||||
if (!row.indexdef.toLowerCase().includes('using hnsw')) {
|
||||
promises.push(this.reindexVectors(indexName));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DatabaseExtension.VECTORS: {
|
||||
case DatabaseExtension.Vectors: {
|
||||
if (!row.indexdef.toLowerCase().includes('using vectors')) {
|
||||
promises.push(this.reindexVectors(indexName));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DatabaseExtension.VECTORCHORD: {
|
||||
case DatabaseExtension.VectorChord: {
|
||||
const matches = row.indexdef.match(/(?<=lists = \[)\d+/g);
|
||||
const lists = matches && matches.length > 0 ? Number(matches[0]) : 1;
|
||||
promises.push(
|
||||
@@ -264,7 +264,7 @@ export class DatabaseRepository {
|
||||
await sql`ALTER TABLE ${sql.raw(table)} ADD COLUMN embedding real[] NOT NULL`.execute(tx);
|
||||
}
|
||||
await sql`ALTER TABLE ${sql.raw(table)} ALTER COLUMN embedding SET DATA TYPE real[]`.execute(tx);
|
||||
const schema = vectorExtension === DatabaseExtension.VECTORS ? 'vectors.' : '';
|
||||
const schema = vectorExtension === DatabaseExtension.Vectors ? 'vectors.' : '';
|
||||
await sql`
|
||||
ALTER TABLE ${sql.raw(table)}
|
||||
ALTER COLUMN embedding
|
||||
@@ -329,11 +329,11 @@ export class DatabaseRepository {
|
||||
.alterColumn('embedding', (col) => col.setDataType(sql.raw(`vector(${dimSize})`)))
|
||||
.execute();
|
||||
await sql
|
||||
.raw(vectorIndexQuery({ vectorExtension, table: 'smart_search', indexName: VectorIndex.CLIP }))
|
||||
.raw(vectorIndexQuery({ vectorExtension, table: 'smart_search', indexName: VectorIndex.Clip }))
|
||||
.execute(trx);
|
||||
await trx.schema.alterTable('smart_search').dropConstraint('dim_size_constraint').ifExists().execute();
|
||||
});
|
||||
probes[VectorIndex.CLIP] = 1;
|
||||
probes[VectorIndex.Clip] = 1;
|
||||
|
||||
await sql`vacuum analyze ${sql.table('smart_search')}`.execute(this.db);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ export class DownloadRepository {
|
||||
downloadUserId(userId: string) {
|
||||
return builder(this.db)
|
||||
.where('asset.ownerId', '=', userId)
|
||||
.where('asset.visibility', '!=', AssetVisibility.HIDDEN)
|
||||
.where('asset.visibility', '!=', AssetVisibility.Hidden)
|
||||
.stream();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,14 +109,14 @@ export class DuplicateRepository {
|
||||
assetId: DummyValue.UUID,
|
||||
embedding: DummyValue.VECTOR,
|
||||
maxDistance: 0.6,
|
||||
type: AssetType.IMAGE,
|
||||
type: AssetType.Image,
|
||||
userIds: [DummyValue.UUID],
|
||||
},
|
||||
],
|
||||
})
|
||||
search({ assetId, embedding, maxDistance, type, userIds }: DuplicateSearch) {
|
||||
return this.db.transaction().execute(async (trx) => {
|
||||
await sql`set local vchordrq.probes = ${sql.lit(probes[VectorIndex.CLIP])}`.execute(trx);
|
||||
await sql`set local vchordrq.probes = ${sql.lit(probes[VectorIndex.Clip])}`.execute(trx);
|
||||
return await trx
|
||||
.with('cte', (qb) =>
|
||||
qb
|
||||
|
||||
@@ -166,7 +166,7 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect
|
||||
continue;
|
||||
}
|
||||
|
||||
const event = reflector.get<EventConfig>(MetadataKey.EVENT_CONFIG, handler);
|
||||
const event = reflector.get<EventConfig>(MetadataKey.EventConfig, handler);
|
||||
if (!event) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export class JobRepository {
|
||||
const instance = this.moduleRef.get<any>(Service);
|
||||
for (const methodName of getMethodNames(instance)) {
|
||||
const handler = instance[methodName];
|
||||
const config = reflector.get<JobConfig>(MetadataKey.JOB_CONFIG, handler);
|
||||
const config = reflector.get<JobConfig>(MetadataKey.JobConfig, handler);
|
||||
if (!config) {
|
||||
continue;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ export class JobRepository {
|
||||
const item = this.handlers[name as JobName];
|
||||
if (!item) {
|
||||
this.logger.warn(`Skipping unknown job: "${name}"`);
|
||||
return JobStatus.SKIPPED;
|
||||
return JobStatus.Skipped;
|
||||
}
|
||||
|
||||
return item.handler(data);
|
||||
@@ -205,20 +205,20 @@ export class JobRepository {
|
||||
|
||||
private getJobOptions(item: JobItem): JobsOptions | null {
|
||||
switch (item.name) {
|
||||
case JobName.NOTIFY_ALBUM_UPDATE: {
|
||||
case JobName.NotifyAlbumUpdate: {
|
||||
return {
|
||||
jobId: `${item.data.id}/${item.data.recipientId}`,
|
||||
delay: item.data?.delay,
|
||||
};
|
||||
}
|
||||
case JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE: {
|
||||
case JobName.StorageTemplateMigrationSingle: {
|
||||
return { jobId: item.data.id };
|
||||
}
|
||||
case JobName.GENERATE_PERSON_THUMBNAIL: {
|
||||
case JobName.GeneratePersonThumbnail: {
|
||||
return { priority: 1 };
|
||||
}
|
||||
case JobName.QUEUE_FACIAL_RECOGNITION: {
|
||||
return { jobId: JobName.QUEUE_FACIAL_RECOGNITION };
|
||||
case JobName.QueueFacialRecognition: {
|
||||
return { jobId: JobName.QueueFacialRecognition };
|
||||
}
|
||||
default: {
|
||||
return null;
|
||||
|
||||
@@ -79,7 +79,7 @@ export class LibraryRepository {
|
||||
eb.fn
|
||||
.countAll<number>()
|
||||
.filterWhere((eb) =>
|
||||
eb.and([eb('asset.type', '=', AssetType.IMAGE), eb('asset.visibility', '!=', AssetVisibility.HIDDEN)]),
|
||||
eb.and([eb('asset.type', '=', AssetType.Image), eb('asset.visibility', '!=', AssetVisibility.Hidden)]),
|
||||
)
|
||||
.as('photos'),
|
||||
)
|
||||
@@ -87,7 +87,7 @@ export class LibraryRepository {
|
||||
eb.fn
|
||||
.countAll<number>()
|
||||
.filterWhere((eb) =>
|
||||
eb.and([eb('asset.type', '=', AssetType.VIDEO), eb('asset.visibility', '!=', AssetVisibility.HIDDEN)]),
|
||||
eb.and([eb('asset.type', '=', AssetType.Video), eb('asset.visibility', '!=', AssetVisibility.Hidden)]),
|
||||
)
|
||||
.as('videos'),
|
||||
)
|
||||
|
||||
@@ -22,7 +22,7 @@ describe(LoggingRepository.name, () => {
|
||||
describe('formatContext', () => {
|
||||
it('should use colors', () => {
|
||||
sut = new LoggingRepository(clsMock, configMock);
|
||||
sut.setAppName(ImmichWorker.API);
|
||||
sut.setAppName(ImmichWorker.Api);
|
||||
|
||||
const logger = new MyConsoleLogger(clsMock, { color: true });
|
||||
|
||||
@@ -31,7 +31,7 @@ describe(LoggingRepository.name, () => {
|
||||
|
||||
it('should not use colors when color is false', () => {
|
||||
sut = new LoggingRepository(clsMock, configMock);
|
||||
sut.setAppName(ImmichWorker.API);
|
||||
sut.setAppName(ImmichWorker.Api);
|
||||
|
||||
const logger = new MyConsoleLogger(clsMock, { color: false });
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ConfigRepository } from 'src/repositories/config.repository';
|
||||
type LogDetails = any;
|
||||
type LogFunction = () => string;
|
||||
|
||||
const LOG_LEVELS = [LogLevel.VERBOSE, LogLevel.DEBUG, LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL];
|
||||
const LOG_LEVELS = [LogLevel.Verbose, LogLevel.Debug, LogLevel.Log, LogLevel.Warn, LogLevel.Error, LogLevel.Fatal];
|
||||
|
||||
enum LogColor {
|
||||
RED = 31,
|
||||
@@ -20,7 +20,7 @@ enum LogColor {
|
||||
}
|
||||
|
||||
let appName: string | undefined;
|
||||
let logLevels: LogLevel[] = [LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL];
|
||||
let logLevels: LogLevel[] = [LogLevel.Log, LogLevel.Warn, LogLevel.Error, LogLevel.Fatal];
|
||||
|
||||
export class MyConsoleLogger extends ConsoleLogger {
|
||||
private isColorEnabled: boolean;
|
||||
@@ -106,35 +106,35 @@ export class LoggingRepository {
|
||||
}
|
||||
|
||||
verbose(message: string, ...details: LogDetails) {
|
||||
this.handleMessage(LogLevel.VERBOSE, message, details);
|
||||
this.handleMessage(LogLevel.Verbose, message, details);
|
||||
}
|
||||
|
||||
verboseFn(message: LogFunction, ...details: LogDetails) {
|
||||
this.handleFunction(LogLevel.VERBOSE, message, details);
|
||||
this.handleFunction(LogLevel.Verbose, message, details);
|
||||
}
|
||||
|
||||
debug(message: string, ...details: LogDetails) {
|
||||
this.handleMessage(LogLevel.DEBUG, message, details);
|
||||
this.handleMessage(LogLevel.Debug, message, details);
|
||||
}
|
||||
|
||||
debugFn(message: LogFunction, ...details: LogDetails) {
|
||||
this.handleFunction(LogLevel.DEBUG, message, details);
|
||||
this.handleFunction(LogLevel.Debug, message, details);
|
||||
}
|
||||
|
||||
log(message: string, ...details: LogDetails) {
|
||||
this.handleMessage(LogLevel.LOG, message, details);
|
||||
this.handleMessage(LogLevel.Log, message, details);
|
||||
}
|
||||
|
||||
warn(message: string, ...details: LogDetails) {
|
||||
this.handleMessage(LogLevel.WARN, message, details);
|
||||
this.handleMessage(LogLevel.Warn, message, details);
|
||||
}
|
||||
|
||||
error(message: string | Error, ...details: LogDetails) {
|
||||
this.handleMessage(LogLevel.ERROR, message, details);
|
||||
this.handleMessage(LogLevel.Error, message, details);
|
||||
}
|
||||
|
||||
fatal(message: string, ...details: LogDetails) {
|
||||
this.handleMessage(LogLevel.FATAL, message, details);
|
||||
this.handleMessage(LogLevel.Fatal, message, details);
|
||||
}
|
||||
|
||||
private handleFunction(level: LogLevel, message: LogFunction, details: LogDetails[]) {
|
||||
@@ -145,32 +145,32 @@ export class LoggingRepository {
|
||||
|
||||
private handleMessage(level: LogLevel, message: string | Error, details: LogDetails[]) {
|
||||
switch (level) {
|
||||
case LogLevel.VERBOSE: {
|
||||
case LogLevel.Verbose: {
|
||||
this.logger.verbose(message, ...details);
|
||||
break;
|
||||
}
|
||||
|
||||
case LogLevel.DEBUG: {
|
||||
case LogLevel.Debug: {
|
||||
this.logger.debug(message, ...details);
|
||||
break;
|
||||
}
|
||||
|
||||
case LogLevel.LOG: {
|
||||
case LogLevel.Log: {
|
||||
this.logger.log(message, ...details);
|
||||
break;
|
||||
}
|
||||
|
||||
case LogLevel.WARN: {
|
||||
case LogLevel.Warn: {
|
||||
this.logger.warn(message, ...details);
|
||||
break;
|
||||
}
|
||||
|
||||
case LogLevel.ERROR: {
|
||||
case LogLevel.Error: {
|
||||
this.logger.error(message, ...details);
|
||||
break;
|
||||
}
|
||||
|
||||
case LogLevel.FATAL: {
|
||||
case LogLevel.Fatal: {
|
||||
this.logger.fatal(message, ...details);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -61,14 +61,14 @@ export class MapRepository {
|
||||
const geodataDate = await readFile(resourcePaths.geodata.dateFile, 'utf8');
|
||||
|
||||
// TODO move to service init
|
||||
const geocodingMetadata = await this.metadataRepository.get(SystemMetadataKey.REVERSE_GEOCODING_STATE);
|
||||
const geocodingMetadata = await this.metadataRepository.get(SystemMetadataKey.ReverseGeocodingState);
|
||||
if (geocodingMetadata?.lastUpdate === geodataDate) {
|
||||
return;
|
||||
}
|
||||
|
||||
await Promise.all([this.importGeodata(), this.importNaturalEarthCountries()]);
|
||||
|
||||
await this.metadataRepository.set(SystemMetadataKey.REVERSE_GEOCODING_STATE, {
|
||||
await this.metadataRepository.set(SystemMetadataKey.ReverseGeocodingState, {
|
||||
lastUpdate: geodataDate,
|
||||
lastImportFileName: citiesFile,
|
||||
});
|
||||
@@ -102,13 +102,13 @@ export class MapRepository {
|
||||
.$if(isArchived === true, (qb) =>
|
||||
qb.where((eb) =>
|
||||
eb.or([
|
||||
eb('asset.visibility', '=', AssetVisibility.TIMELINE),
|
||||
eb('asset.visibility', '=', AssetVisibility.ARCHIVE),
|
||||
eb('asset.visibility', '=', AssetVisibility.Timeline),
|
||||
eb('asset.visibility', '=', AssetVisibility.Archive),
|
||||
]),
|
||||
),
|
||||
)
|
||||
.$if(isArchived === false || isArchived === undefined, (qb) =>
|
||||
qb.where('asset.visibility', '=', AssetVisibility.TIMELINE),
|
||||
qb.where('asset.visibility', '=', AssetVisibility.Timeline),
|
||||
)
|
||||
.$if(isFavorite !== undefined, (q) => q.where('isFavorite', '=', isFavorite!))
|
||||
.$if(fileCreatedAfter !== undefined, (q) => q.where('fileCreatedAt', '>=', fileCreatedAfter!))
|
||||
|
||||
@@ -55,28 +55,28 @@ export class MediaRepository {
|
||||
async extract(input: string): Promise<ExtractResult | null> {
|
||||
try {
|
||||
const buffer = await exiftool.extractBinaryTagToBuffer('JpgFromRaw2', input);
|
||||
return { buffer, format: RawExtractedFormat.JPEG };
|
||||
return { buffer, format: RawExtractedFormat.Jpeg };
|
||||
} catch (error: any) {
|
||||
this.logger.debug('Could not extract JpgFromRaw2 buffer from image, trying JPEG from RAW next', error.message);
|
||||
}
|
||||
|
||||
try {
|
||||
const buffer = await exiftool.extractBinaryTagToBuffer('JpgFromRaw', input);
|
||||
return { buffer, format: RawExtractedFormat.JPEG };
|
||||
return { buffer, format: RawExtractedFormat.Jpeg };
|
||||
} catch (error: any) {
|
||||
this.logger.debug('Could not extract JPEG buffer from image, trying PreviewJXL next', error.message);
|
||||
}
|
||||
|
||||
try {
|
||||
const buffer = await exiftool.extractBinaryTagToBuffer('PreviewJXL', input);
|
||||
return { buffer, format: RawExtractedFormat.JXL };
|
||||
return { buffer, format: RawExtractedFormat.Jxl };
|
||||
} catch (error: any) {
|
||||
this.logger.debug('Could not extract PreviewJXL buffer from image, trying PreviewImage next', error.message);
|
||||
}
|
||||
|
||||
try {
|
||||
const buffer = await exiftool.extractBinaryTagToBuffer('PreviewImage', input);
|
||||
return { buffer, format: RawExtractedFormat.JPEG };
|
||||
return { buffer, format: RawExtractedFormat.Jpeg };
|
||||
} catch (error: any) {
|
||||
this.logger.debug('Could not extract preview buffer from image', error.message);
|
||||
return null;
|
||||
@@ -142,7 +142,7 @@ export class MediaRepository {
|
||||
limitInputPixels: false,
|
||||
raw: options.raw,
|
||||
})
|
||||
.pipelineColorspace(options.colorspace === Colorspace.SRGB ? 'srgb' : 'rgb16')
|
||||
.pipelineColorspace(options.colorspace === Colorspace.Srgb ? 'srgb' : 'rgb16')
|
||||
.withIccProfile(options.colorspace);
|
||||
|
||||
if (!options.raw) {
|
||||
@@ -267,7 +267,7 @@ export class MediaRepository {
|
||||
|
||||
const { frameCount, percentInterval } = options.progress;
|
||||
const frameInterval = Math.ceil(frameCount / (100 / percentInterval));
|
||||
if (this.logger.isLevelEnabled(LogLevel.DEBUG) && frameCount && frameInterval) {
|
||||
if (this.logger.isLevelEnabled(LogLevel.Debug) && frameCount && frameInterval) {
|
||||
let lastProgressFrame: number = 0;
|
||||
ffmpegCall.on('progress', (progress: ProgressEvent) => {
|
||||
if (progress.frames - lastProgressFrame < frameInterval) {
|
||||
|
||||
@@ -19,7 +19,7 @@ export class MemoryRepository implements IBulkAsset {
|
||||
.deleteFrom('memory_asset')
|
||||
.using('asset')
|
||||
.whereRef('memory_asset.assetsId', '=', 'asset.id')
|
||||
.where('asset.visibility', '!=', AssetVisibility.TIMELINE)
|
||||
.where('asset.visibility', '!=', AssetVisibility.Timeline)
|
||||
.execute();
|
||||
|
||||
return this.db
|
||||
@@ -67,7 +67,7 @@ export class MemoryRepository implements IBulkAsset {
|
||||
.innerJoin('memory_asset', 'asset.id', 'memory_asset.assetsId')
|
||||
.whereRef('memory_asset.memoriesId', '=', 'memory.id')
|
||||
.orderBy('asset.fileCreatedAt', 'asc')
|
||||
.where('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
|
||||
.where('asset.visibility', '=', sql.lit(AssetVisibility.Timeline))
|
||||
.where('asset.deletedAt', 'is', null),
|
||||
).as('assets'),
|
||||
)
|
||||
@@ -158,7 +158,7 @@ export class MemoryRepository implements IBulkAsset {
|
||||
.innerJoin('memory_asset', 'asset.id', 'memory_asset.assetsId')
|
||||
.whereRef('memory_asset.memoriesId', '=', 'memory.id')
|
||||
.orderBy('asset.fileCreatedAt', 'asc')
|
||||
.where('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
|
||||
.where('asset.visibility', '=', sql.lit(AssetVisibility.Timeline))
|
||||
.where('asset.deletedAt', 'is', null),
|
||||
).as('assets'),
|
||||
)
|
||||
|
||||
@@ -48,7 +48,7 @@ export class MoveRepository {
|
||||
eb.selectFrom('asset').select('id').whereRef('asset.id', '=', 'move_history.entityId'),
|
||||
),
|
||||
)
|
||||
.where('move_history.pathType', '=', sql.lit(AssetPathType.ORIGINAL))
|
||||
.where('move_history.pathType', '=', sql.lit(AssetPathType.Original))
|
||||
.execute();
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export class MoveRepository {
|
||||
async cleanMoveHistorySingle(assetId: string): Promise<void> {
|
||||
await this.db
|
||||
.deleteFrom('move_history')
|
||||
.where('move_history.pathType', '=', sql.lit(AssetPathType.ORIGINAL))
|
||||
.where('move_history.pathType', '=', sql.lit(AssetPathType.Original))
|
||||
.where('entityId', '=', assetId)
|
||||
.execute();
|
||||
}
|
||||
|
||||
@@ -138,11 +138,11 @@ export class OAuthRepository {
|
||||
}
|
||||
|
||||
switch (tokenEndpointAuthMethod) {
|
||||
case OAuthTokenEndpointAuthMethod.CLIENT_SECRET_POST: {
|
||||
case OAuthTokenEndpointAuthMethod.ClientSecretPost: {
|
||||
return ClientSecretPost(clientSecret);
|
||||
}
|
||||
|
||||
case OAuthTokenEndpointAuthMethod.CLIENT_SECRET_BASIC: {
|
||||
case OAuthTokenEndpointAuthMethod.ClientSecretBasic: {
|
||||
return ClientSecretBasic(clientSecret);
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ export class PersonRepository {
|
||||
.innerJoin('asset', (join) =>
|
||||
join
|
||||
.onRef('asset_face.assetId', '=', 'asset.id')
|
||||
.on('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
|
||||
.on('asset.visibility', '=', sql.lit(AssetVisibility.Timeline))
|
||||
.on('asset.deletedAt', 'is', null),
|
||||
)
|
||||
.where('person.ownerId', '=', userId)
|
||||
@@ -276,7 +276,7 @@ export class PersonRepository {
|
||||
.selectFrom('asset_file')
|
||||
.select('asset_file.path')
|
||||
.whereRef('asset_file.assetId', '=', 'asset.id')
|
||||
.where('asset_file.type', '=', sql.lit(AssetFileType.PREVIEW))
|
||||
.where('asset_file.type', '=', sql.lit(AssetFileType.Preview))
|
||||
.as('previewPath'),
|
||||
)
|
||||
.where('person.id', '=', id)
|
||||
@@ -341,7 +341,7 @@ export class PersonRepository {
|
||||
join
|
||||
.onRef('asset.id', '=', 'asset_face.assetId')
|
||||
.on('asset_face.personId', '=', personId)
|
||||
.on('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
|
||||
.on('asset.visibility', '=', sql.lit(AssetVisibility.Timeline))
|
||||
.on('asset.deletedAt', 'is', null),
|
||||
)
|
||||
.select((eb) => eb.fn.count(eb.fn('distinct', ['asset.id'])).as('count'))
|
||||
@@ -369,7 +369,7 @@ export class PersonRepository {
|
||||
eb
|
||||
.selectFrom('asset')
|
||||
.whereRef('asset.id', '=', 'asset_face.assetId')
|
||||
.where('asset.visibility', '=', sql.lit(AssetVisibility.TIMELINE))
|
||||
.where('asset.visibility', '=', sql.lit(AssetVisibility.Timeline))
|
||||
.where('asset.deletedAt', 'is', null),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -256,7 +256,7 @@ export class SearchRepository {
|
||||
}
|
||||
|
||||
return this.db.transaction().execute(async (trx) => {
|
||||
await sql`set local vchordrq.probes = ${sql.lit(probes[VectorIndex.CLIP])}`.execute(trx);
|
||||
await sql`set local vchordrq.probes = ${sql.lit(probes[VectorIndex.Clip])}`.execute(trx);
|
||||
const items = await searchAssetBuilder(trx, options)
|
||||
.selectAll('asset')
|
||||
.innerJoin('smart_search', 'asset.id', 'smart_search.assetId')
|
||||
@@ -284,7 +284,7 @@ export class SearchRepository {
|
||||
}
|
||||
|
||||
return this.db.transaction().execute(async (trx) => {
|
||||
await sql`set local vchordrq.probes = ${sql.lit(probes[VectorIndex.FACE])}`.execute(trx);
|
||||
await sql`set local vchordrq.probes = ${sql.lit(probes[VectorIndex.Face])}`.execute(trx);
|
||||
return await trx
|
||||
.with('cte', (qb) =>
|
||||
qb
|
||||
@@ -351,8 +351,8 @@ export class SearchRepository {
|
||||
.select(['city', 'assetId'])
|
||||
.innerJoin('asset', 'asset.id', 'asset_exif.assetId')
|
||||
.where('asset.ownerId', '=', anyUuid(userIds))
|
||||
.where('asset.visibility', '=', AssetVisibility.TIMELINE)
|
||||
.where('asset.type', '=', AssetType.IMAGE)
|
||||
.where('asset.visibility', '=', AssetVisibility.Timeline)
|
||||
.where('asset.type', '=', AssetType.Image)
|
||||
.where('asset.deletedAt', 'is', null)
|
||||
.orderBy('city')
|
||||
.limit(1);
|
||||
@@ -367,8 +367,8 @@ export class SearchRepository {
|
||||
.select(['city', 'assetId'])
|
||||
.innerJoin('asset', 'asset.id', 'asset_exif.assetId')
|
||||
.where('asset.ownerId', '=', anyUuid(userIds))
|
||||
.where('asset.visibility', '=', AssetVisibility.TIMELINE)
|
||||
.where('asset.type', '=', AssetType.IMAGE)
|
||||
.where('asset.visibility', '=', AssetVisibility.Timeline)
|
||||
.where('asset.type', '=', AssetType.Image)
|
||||
.where('asset.deletedAt', 'is', null)
|
||||
.whereRef('asset_exif.city', '>', 'cte.city')
|
||||
.orderBy('city')
|
||||
@@ -450,7 +450,7 @@ export class SearchRepository {
|
||||
.distinctOn(field)
|
||||
.innerJoin('asset', 'asset.id', 'asset_exif.assetId')
|
||||
.where('ownerId', '=', anyUuid(userIds))
|
||||
.where('visibility', '=', AssetVisibility.TIMELINE)
|
||||
.where('visibility', '=', AssetVisibility.Timeline)
|
||||
.where('deletedAt', 'is', null)
|
||||
.where(field, 'is not', null);
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ export class SharedLinkRepository {
|
||||
.select((eb) => eb.fn.toJson('album').$castTo<Album | null>().as('album'))
|
||||
.where('shared_link.id', '=', id)
|
||||
.where('shared_link.userId', '=', userId)
|
||||
.where((eb) => eb.or([eb('shared_link.type', '=', SharedLinkType.INDIVIDUAL), eb('album.id', 'is not', null)]))
|
||||
.where((eb) => eb.or([eb('shared_link.type', '=', SharedLinkType.Individual), eb('album.id', 'is not', null)]))
|
||||
.orderBy('shared_link.createdAt', 'desc')
|
||||
.executeTakeFirst();
|
||||
}
|
||||
@@ -165,7 +165,7 @@ export class SharedLinkRepository {
|
||||
(join) => join.onTrue(),
|
||||
)
|
||||
.select((eb) => eb.fn.toJson('album').$castTo<Album | null>().as('album'))
|
||||
.where((eb) => eb.or([eb('shared_link.type', '=', SharedLinkType.INDIVIDUAL), eb('album.id', 'is not', null)]))
|
||||
.where((eb) => eb.or([eb('shared_link.type', '=', SharedLinkType.Individual), eb('album.id', 'is not', null)]))
|
||||
.$if(!!albumId, (eb) => eb.where('shared_link.albumId', '=', albumId!))
|
||||
.orderBy('shared_link.createdAt', 'desc')
|
||||
.distinctOn(['shared_link.createdAt'])
|
||||
@@ -185,7 +185,7 @@ export class SharedLinkRepository {
|
||||
eb.selectFrom('user').select(columns.authUser).whereRef('user.id', '=', 'shared_link.userId'),
|
||||
).as('user'),
|
||||
])
|
||||
.where((eb) => eb.or([eb('shared_link.type', '=', SharedLinkType.INDIVIDUAL), eb('album.id', 'is not', null)]))
|
||||
.where((eb) => eb.or([eb('shared_link.type', '=', SharedLinkType.Individual), eb('album.id', 'is not', null)]))
|
||||
.executeTakeFirst();
|
||||
}
|
||||
|
||||
|
||||
@@ -112,21 +112,21 @@ export class TelemetryRepository {
|
||||
const { telemetry } = this.configRepository.getEnv();
|
||||
const { metrics } = telemetry;
|
||||
|
||||
this.api = new MetricGroupRepository(metricService).configure({ enabled: metrics.has(ImmichTelemetry.API) });
|
||||
this.host = new MetricGroupRepository(metricService).configure({ enabled: metrics.has(ImmichTelemetry.HOST) });
|
||||
this.jobs = new MetricGroupRepository(metricService).configure({ enabled: metrics.has(ImmichTelemetry.JOB) });
|
||||
this.repo = new MetricGroupRepository(metricService).configure({ enabled: metrics.has(ImmichTelemetry.REPO) });
|
||||
this.api = new MetricGroupRepository(metricService).configure({ enabled: metrics.has(ImmichTelemetry.Api) });
|
||||
this.host = new MetricGroupRepository(metricService).configure({ enabled: metrics.has(ImmichTelemetry.Host) });
|
||||
this.jobs = new MetricGroupRepository(metricService).configure({ enabled: metrics.has(ImmichTelemetry.Job) });
|
||||
this.repo = new MetricGroupRepository(metricService).configure({ enabled: metrics.has(ImmichTelemetry.Repo) });
|
||||
}
|
||||
|
||||
setup({ repositories }: { repositories: ClassConstructor<unknown>[] }) {
|
||||
const { telemetry } = this.configRepository.getEnv();
|
||||
const { metrics } = telemetry;
|
||||
if (!metrics.has(ImmichTelemetry.REPO)) {
|
||||
if (!metrics.has(ImmichTelemetry.Repo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const Repository of repositories) {
|
||||
const isEnabled = this.reflect.get(MetadataKey.TELEMETRY_ENABLED, Repository) ?? true;
|
||||
const isEnabled = this.reflect.get(MetadataKey.TelemetryEnabled, Repository) ?? true;
|
||||
if (!isEnabled) {
|
||||
this.logger.debug(`Telemetry disabled for ${Repository.name}`);
|
||||
continue;
|
||||
|
||||
@@ -8,7 +8,7 @@ export class TrashRepository {
|
||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||
|
||||
getDeletedIds(): AsyncIterableIterator<{ id: string }> {
|
||||
return this.db.selectFrom('asset').select(['id']).where('status', '=', AssetStatus.DELETED).stream();
|
||||
return this.db.selectFrom('asset').select(['id']).where('status', '=', AssetStatus.Deleted).stream();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID] })
|
||||
@@ -16,8 +16,8 @@ export class TrashRepository {
|
||||
const { numUpdatedRows } = await this.db
|
||||
.updateTable('asset')
|
||||
.where('ownerId', '=', userId)
|
||||
.where('status', '=', AssetStatus.TRASHED)
|
||||
.set({ status: AssetStatus.ACTIVE, deletedAt: null })
|
||||
.where('status', '=', AssetStatus.Trashed)
|
||||
.set({ status: AssetStatus.Active, deletedAt: null })
|
||||
.executeTakeFirst();
|
||||
|
||||
return Number(numUpdatedRows);
|
||||
@@ -28,8 +28,8 @@ export class TrashRepository {
|
||||
const { numUpdatedRows } = await this.db
|
||||
.updateTable('asset')
|
||||
.where('ownerId', '=', userId)
|
||||
.where('status', '=', AssetStatus.TRASHED)
|
||||
.set({ status: AssetStatus.DELETED })
|
||||
.where('status', '=', AssetStatus.Trashed)
|
||||
.set({ status: AssetStatus.Deleted })
|
||||
.executeTakeFirst();
|
||||
|
||||
return Number(numUpdatedRows);
|
||||
@@ -43,9 +43,9 @@ export class TrashRepository {
|
||||
|
||||
const { numUpdatedRows } = await this.db
|
||||
.updateTable('asset')
|
||||
.where('status', '=', AssetStatus.TRASHED)
|
||||
.where('status', '=', AssetStatus.Trashed)
|
||||
.where('id', 'in', ids)
|
||||
.set({ status: AssetStatus.ACTIVE, deletedAt: null })
|
||||
.set({ status: AssetStatus.Active, deletedAt: null })
|
||||
.executeTakeFirst();
|
||||
|
||||
return Number(numUpdatedRows);
|
||||
|
||||
@@ -187,7 +187,7 @@ export class UserRepository {
|
||||
restore(id: string) {
|
||||
return this.db
|
||||
.updateTable('user')
|
||||
.set({ status: UserStatus.ACTIVE, deletedAt: null })
|
||||
.set({ status: UserStatus.Active, deletedAt: null })
|
||||
.where('user.id', '=', asUuid(id))
|
||||
.returning(columns.userAdmin)
|
||||
.returning(withMetadata)
|
||||
@@ -229,8 +229,8 @@ export class UserRepository {
|
||||
.countAll<number>()
|
||||
.filterWhere((eb) =>
|
||||
eb.and([
|
||||
eb('asset.type', '=', sql.lit(AssetType.IMAGE)),
|
||||
eb('asset.visibility', '!=', sql.lit(AssetVisibility.HIDDEN)),
|
||||
eb('asset.type', '=', sql.lit(AssetType.Image)),
|
||||
eb('asset.visibility', '!=', sql.lit(AssetVisibility.Hidden)),
|
||||
]),
|
||||
)
|
||||
.as('photos'),
|
||||
@@ -238,8 +238,8 @@ export class UserRepository {
|
||||
.countAll<number>()
|
||||
.filterWhere((eb) =>
|
||||
eb.and([
|
||||
eb('asset.type', '=', sql.lit(AssetType.VIDEO)),
|
||||
eb('asset.visibility', '!=', sql.lit(AssetVisibility.HIDDEN)),
|
||||
eb('asset.type', '=', sql.lit(AssetType.Video)),
|
||||
eb('asset.visibility', '!=', sql.lit(AssetVisibility.Hidden)),
|
||||
]),
|
||||
)
|
||||
.as('videos'),
|
||||
@@ -254,7 +254,7 @@ export class UserRepository {
|
||||
eb.fn
|
||||
.sum<number>('asset_exif.fileSizeInByte')
|
||||
.filterWhere((eb) =>
|
||||
eb.and([eb('asset.libraryId', 'is', null), eb('asset.type', '=', sql.lit(AssetType.IMAGE))]),
|
||||
eb.and([eb('asset.libraryId', 'is', null), eb('asset.type', '=', sql.lit(AssetType.Image))]),
|
||||
),
|
||||
eb.lit(0),
|
||||
)
|
||||
@@ -264,7 +264,7 @@ export class UserRepository {
|
||||
eb.fn
|
||||
.sum<number>('asset_exif.fileSizeInByte')
|
||||
.filterWhere((eb) =>
|
||||
eb.and([eb('asset.libraryId', 'is', null), eb('asset.type', '=', sql.lit(AssetType.VIDEO))]),
|
||||
eb.and([eb('asset.libraryId', 'is', null), eb('asset.type', '=', sql.lit(AssetType.Video))]),
|
||||
),
|
||||
eb.lit(0),
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@ export class ViewRepository {
|
||||
.select((eb) => eb.fn<string>('substring', ['asset.originalPath', eb.val('^(.*/)[^/]*$')]).as('directoryPath'))
|
||||
.distinct()
|
||||
.where('ownerId', '=', asUuid(userId))
|
||||
.where('visibility', '=', AssetVisibility.TIMELINE)
|
||||
.where('visibility', '=', AssetVisibility.Timeline)
|
||||
.where('deletedAt', 'is', null)
|
||||
.where('fileCreatedAt', 'is not', null)
|
||||
.where('fileModifiedAt', 'is not', null)
|
||||
@@ -34,7 +34,7 @@ export class ViewRepository {
|
||||
.selectAll('asset')
|
||||
.$call(withExif)
|
||||
.where('ownerId', '=', asUuid(userId))
|
||||
.where('visibility', '=', AssetVisibility.TIMELINE)
|
||||
.where('visibility', '=', AssetVisibility.Timeline)
|
||||
.where('deletedAt', 'is', null)
|
||||
.where('fileCreatedAt', 'is not', null)
|
||||
.where('fileModifiedAt', 'is not', null)
|
||||
|
||||
Reference in New Issue
Block a user