From 11755e5a53ea488626c401b6331f224080d5fe4f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Aug 2026 12:00:16 +0200 Subject: [PATCH] chore(deps): update dependency eslint-plugin-unicorn to v73 (#30844) Co-authored-by: Daniel Dietzler --- e2e/package.json | 2 +- e2e/src/specs/server/api/user.e2e-spec.ts | 4 +- packages/cli/package.json | 2 +- pnpm-lock.yaml | 22 ++-- server/package.json | 2 +- .../system-config.controller.spec.ts | 4 +- server/src/decorators.ts | 20 +++- server/src/dtos/asset-ids.response.dto.ts | 12 +- server/src/dtos/asset-media.dto.ts | 4 +- server/src/dtos/system-config.dto.ts | 4 +- server/src/enum.ts | 104 +++++++++++++----- server/src/middleware/auth.guard.ts | 4 +- server/src/repositories/event.repository.ts | 28 +++-- server/src/repositories/job.repository.ts | 4 +- server/src/repositories/media.repository.ts | 4 +- server/src/repositories/search.repository.ts | 4 +- server/src/schema/tables/memory.table.ts | 12 +- server/src/services/auth.service.ts | 4 +- server/src/services/metadata.service.ts | 4 +- server/src/types.ts | 40 +++++-- server/src/utils/asset.util.ts | 4 +- server/src/utils/database.ts | 4 +- server/src/utils/mime-types.ts | 4 +- server/src/utils/workflow.ts | 4 +- server/test/fixtures/media.stub.ts | 4 +- server/test/utils.ts | 2 - web/package.json | 2 +- web/src/lib/actions/focus.ts | 4 +- .../components/album-page/AlbumsList.svelte | 12 +- .../PhotoSphereViewerAdapter.svelte | 4 +- .../lib/components/timeline/Scrubber.svelte | 48 ++++++-- web/src/lib/utils/album-utils.ts | 24 +++- web/src/lib/utils/invocationTracker.ts | 8 +- web/src/lib/utils/navigation.ts | 4 +- web/src/params/id.ts | 4 +- .../routes/(user)/places/PlacesList.svelte | 8 +- 36 files changed, 309 insertions(+), 115 deletions(-) diff --git a/e2e/package.json b/e2e/package.json index 6f38758a5..88183f89d 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -40,7 +40,7 @@ "eslint": "^10.0.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-unicorn": "^72.0.0", + "eslint-plugin-unicorn": "^73.0.0", "exiftool-vendored": "^35.0.0", "globals": "^17.0.0", "luxon": "^3.4.4", diff --git a/e2e/src/specs/server/api/user.e2e-spec.ts b/e2e/src/specs/server/api/user.e2e-spec.ts index 0e62672f3..c92246dc4 100644 --- a/e2e/src/specs/server/api/user.e2e-spec.ts +++ b/e2e/src/specs/server/api/user.e2e-spec.ts @@ -29,7 +29,9 @@ describe('/users', () => { }); describe('PUT /users/me', () => { - /** @deprecated */ + /** + @deprecated + */ it('should allow a user to change their password (deprecated)', async () => { const user = await getMyUser({ headers: asBearerAuth(nonAdmin.accessToken) }); diff --git a/packages/cli/package.json b/packages/cli/package.json index 9540cefd4..c5ee0e4ee 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -33,7 +33,7 @@ "eslint": "^10.0.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-unicorn": "^72.0.0", + "eslint-plugin-unicorn": "^73.0.0", "globals": "^17.0.0", "mock-fs": "^5.2.0", "prettier": "^3.7.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a24e61a88..317066697 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -157,8 +157,8 @@ importers: specifier: ^5.1.3 version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)))(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1))(prettier@3.9.6) eslint-plugin-unicorn: - specifier: ^72.0.0 - version: 72.0.0(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)) + specifier: ^73.0.0 + version: 73.0.0(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)) exiftool-vendored: specifier: ^35.0.0 version: 35.21.0 @@ -269,8 +269,8 @@ importers: specifier: ^5.1.3 version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)))(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1))(prettier@3.9.6) eslint-plugin-unicorn: - specifier: ^72.0.0 - version: 72.0.0(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)) + specifier: ^73.0.0 + version: 73.0.0(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)) globals: specifier: ^17.0.0 version: 17.9.0 @@ -741,8 +741,8 @@ importers: specifier: ^5.1.3 version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)))(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1))(prettier@3.9.6) eslint-plugin-unicorn: - specifier: ^72.0.0 - version: 72.0.0(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)) + specifier: ^73.0.0 + version: 73.0.0(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)) globals: specifier: ^17.0.0 version: 17.9.0 @@ -1006,8 +1006,8 @@ importers: specifier: ^3.12.4 version: 3.22.0(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1))(svelte@5.56.8(@typescript-eslint/types@8.66.0)) eslint-plugin-unicorn: - specifier: ^72.0.0 - version: 72.0.0(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)) + specifier: ^73.0.0 + version: 73.0.0(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)) factory.ts: specifier: ^1.4.1 version: 1.4.2 @@ -7582,8 +7582,8 @@ packages: svelte: optional: true - eslint-plugin-unicorn@72.0.0: - resolution: {integrity: sha512-hqO6ksoOHO+ZhdseTuKRVQbx9U7PRO/cv8qAR1mctwzdVO2hYud8uS9luAhp43RJgziYgHAph8eHyipT8GL0ng==} + eslint-plugin-unicorn@73.0.0: + resolution: {integrity: sha512-V0YatLe9nkGhXEXKe2Qljb1EY0sJHwDV0HUF1NKFwtsHh/fU7qGHDgv+6fchzZcgU2/7noHo2gdjnmo0P2uDPw==} engines: {node: '>=22'} peerDependencies: eslint: '>=10.4' @@ -20606,7 +20606,7 @@ snapshots: transitivePeerDependencies: - ts-node - eslint-plugin-unicorn@72.0.0(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)): + eslint-plugin-unicorn@73.0.0(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)): dependencies: '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.0(jiti@2.7.0)(supports-color@8.1.1)) '@eslint/css-tree': 4.0.5 diff --git a/server/package.json b/server/package.json index 7d5f73cc6..236a696af 100644 --- a/server/package.json +++ b/server/package.json @@ -151,7 +151,7 @@ "eslint": "^10.0.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-unicorn": "^72.0.0", + "eslint-plugin-unicorn": "^73.0.0", "globals": "^17.0.0", "mock-fs": "^5.2.0", "pngjs": "^7.0.0", diff --git a/server/src/controllers/system-config.controller.spec.ts b/server/src/controllers/system-config.controller.spec.ts index 7d40f1258..862a44879 100644 --- a/server/src/controllers/system-config.controller.spec.ts +++ b/server/src/controllers/system-config.controller.spec.ts @@ -7,7 +7,9 @@ import request from 'supertest'; import { errorDto } from 'test/medium/responses'; import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils'; -/** Returns a full config that passes Zod validation (required URLs and min lengths). */ +/** +Returns a full config that passes Zod validation (required URLs and min lengths). +*/ function validConfig() { const config = _.cloneDeep(defaults) as typeof defaults & { oauth: { mobileRedirectUri: string }; diff --git a/server/src/decorators.ts b/server/src/decorators.ts index 07398b005..322c6c2d3 100644 --- a/server/src/decorators.ts +++ b/server/src/decorators.ts @@ -136,16 +136,24 @@ export interface GenerateSqlQueries { export const Telemetry = (options: { enabled?: boolean }) => SetMetadata(MetadataKey.TelemetryEnabled, options?.enabled ?? true); -/** Decorator to enable versioning/tracking of generated Sql */ +/** +Decorator to enable versioning/tracking of generated Sql +*/ export const GenerateSql = (...options: GenerateSqlQueries[]) => SetMetadata(GENERATE_SQL_KEY, options); export type EventConfig = { name: EmitEvent; - /** handle socket.io server events as well */ + /** + handle socket.io server events as well + */ server?: boolean; - /** lower value has higher priority, defaults to 0 */ + /** + lower value has higher priority, defaults to 0 + */ priority?: number; - /** register events for these workers, defaults to all workers */ + /** + register events for these workers, defaults to all workers + */ workers?: ImmichWorker[]; }; export const OnEvent = (config: EventConfig) => SetMetadata(MetadataKey.EventConfig, config); @@ -183,7 +191,9 @@ type HistoryEntry = { }; type DeprecatedOptions = { - /** replacement operationId */ + /** + replacement operationId + */ replacementId?: string; }; diff --git a/server/src/dtos/asset-ids.response.dto.ts b/server/src/dtos/asset-ids.response.dto.ts index e86eee097..92c73a68c 100644 --- a/server/src/dtos/asset-ids.response.dto.ts +++ b/server/src/dtos/asset-ids.response.dto.ts @@ -1,7 +1,9 @@ import { createZodDto } from 'nestjs-zod'; import z from 'zod'; -/** @deprecated Use `BulkIdResponseDto` instead */ +/** +@deprecated Use `BulkIdResponseDto` instead +*/ export enum AssetIdErrorReason { DUPLICATE = 'duplicate', NO_PERMISSION = 'no_permission', @@ -13,7 +15,9 @@ const AssetIdErrorReasonSchema = z .describe('Error reason if failed') .meta({ id: 'AssetIdErrorReason' }); -/** @deprecated Use `BulkIdResponseDto` instead */ +/** +@deprecated Use `BulkIdResponseDto` instead +*/ const AssetIdsResponseSchema = z .object({ assetId: z.uuidv4().describe('Asset ID'), @@ -50,7 +54,9 @@ const BulkIdResponseSchema = z }) .meta({ id: 'BulkIdResponseDto' }); -/** @deprecated Use `BulkIdResponseDto` instead */ +/** +@deprecated Use `BulkIdResponseDto` instead +*/ export class AssetIdsResponseDto extends createZodDto(AssetIdsResponseSchema) {} export class BulkIdsDto extends createZodDto(BulkIdsSchema) {} export class BulkIdResponseDto extends createZodDto(BulkIdResponseSchema) {} diff --git a/server/src/dtos/asset-media.dto.ts b/server/src/dtos/asset-media.dto.ts index c378a7c74..8393d0bce 100644 --- a/server/src/dtos/asset-media.dto.ts +++ b/server/src/dtos/asset-media.dto.ts @@ -40,7 +40,9 @@ const AssetMediaBaseSchema = z.object({ fileModifiedAt: isoDatetimeToDate.describe('File modification date'), duration: z.coerce.number().int().min(0).optional().describe('Duration in milliseconds (for videos)'), filename: z.string().optional().describe('Filename'), - /** The properties below are added to correctly generate the API docs and client SDKs. Validation should be handled in the controller. */ + /** + The properties below are added to correctly generate the API docs and client SDKs. Validation should be handled in the controller. + */ [UploadFieldName.ASSET_DATA]: z.any().describe('Asset file data').meta({ type: 'string', format: 'binary' }), }); diff --git a/server/src/dtos/system-config.dto.ts b/server/src/dtos/system-config.dto.ts index a50b7abe8..b92445aec 100644 --- a/server/src/dtos/system-config.dto.ts +++ b/server/src/dtos/system-config.dto.ts @@ -23,7 +23,9 @@ import { } from 'src/enum'; import z from 'zod'; -/** Coerces 'true'/'false' strings to boolean, but also allows booleans. */ +/** +Coerces 'true'/'false' strings to boolean, but also allows booleans. +*/ const configBool = z .preprocess((val) => { if (val === 'true') { diff --git a/server/src/enum.ts b/server/src/enum.ts index e88a9a667..1c41da9eb 100644 --- a/server/src/enum.ts +++ b/server/src/enum.ts @@ -45,9 +45,13 @@ export enum AssetType { export const AssetTypeSchema = z.enum(AssetType).describe('Asset type').meta({ id: 'AssetTypeEnum' }); export enum ChecksumAlgorithm { - /** sha1 checksum of the whole file contents */ + /** + sha1 checksum of the whole file contents + */ sha1File = 'sha1', - /** sha1 checksum of "path:" plus the file path, currently used in external libraries, deprecated */ + /** + sha1 checksum of "path:" plus the file path, currently used in external libraries, deprecated + */ sha1Path = 'sha1-path', } @@ -85,7 +89,9 @@ export enum AssetOrderBy { export const AssetOrderBySchema = z.enum(AssetOrderBy).describe('Asset sorting property').meta({ id: 'AssetOrderBy' }); export enum MemoryType { - /** pictures taken on this day X years ago */ + /** + pictures taken on this day X years ago + */ OnThisDay = 'on_this_day', } @@ -95,7 +101,9 @@ export enum AssetOrderWithRandom { // Include existing values Asc = AssetOrder.Asc, Desc = AssetOrder.Desc, - /** Randomly Ordered */ + /** + Randomly Ordered + */ Random = 'random', } @@ -642,7 +650,9 @@ export enum ExifOrientation { Rotate270CW = 8, } -/** ITU-T H.273 colour primaries codes. */ +/** +ITU-T H.273 colour primaries codes. +*/ export enum ColorPrimaries { Reserved = 0, Bt709 = 1, @@ -659,7 +669,9 @@ export enum ColorPrimaries { Ebu3213 = 22, } -/** ITU-T H.273 transfer characteristics codes. */ +/** +ITU-T H.273 transfer characteristics codes. +*/ export enum ColorTransfer { Reserved = 0, Bt709 = 1, @@ -681,7 +693,9 @@ export enum ColorTransfer { AribStdB67 = 18, } -/** ITU-T H.273 matrix coefficients codes. */ +/** +ITU-T H.273 matrix coefficients codes. +*/ export enum ColorMatrix { Gbr = 0, Bt709 = 1, @@ -700,7 +714,9 @@ export enum ColorMatrix { Ictcp = 14, } -/** H.264 `profile_idc` values. */ +/** +H.264 `profile_idc` values. +*/ // H.264 has a few profiles that have the same value but different names, included so lookup by name works export enum H264Profile { ConstrainedBaseline = 66, @@ -718,7 +734,9 @@ export enum H264Profile { High444Predictive = 244, } -/** HEVC `profile_idc` values. */ +/** +HEVC `profile_idc` values. +*/ export enum HevcProfile { Main = 1, Main10 = 2, @@ -726,14 +744,18 @@ export enum HevcProfile { Rext = 4, } -/** AV1 `seq_profile` values. */ +/** +AV1 `seq_profile` values. +*/ export enum Av1Profile { Main = 0, High = 1, Professional = 2, } -/** MPEG-4 Audio Object Type values for AAC. */ +/** +MPEG-4 Audio Object Type values for AAC. +*/ export enum AacProfile { Main = 1, Lc = 2, @@ -746,7 +768,9 @@ export enum AacProfile { XheAac = 42, } -/** Dolby Vision bitstream profile numbers from the DOVI configuration record. */ +/** +Dolby Vision bitstream profile numbers from the DOVI configuration record. +*/ export enum DvProfile { Dvhe03 = 3, Dvhe04 = 4, @@ -922,13 +946,21 @@ export const JobNameSchema = z.enum(JobName).describe('Job name').meta({ id: 'Jo export enum QueueCommand { Start = 'start', - /** @deprecated Use `updateQueue` instead */ + /** + @deprecated Use `updateQueue` instead + */ Pause = 'pause', - /** @deprecated Use `updateQueue` instead */ + /** + @deprecated Use `updateQueue` instead + */ Resume = 'resume', - /** @deprecated Use `emptyQueue` instead */ + /** + @deprecated Use `emptyQueue` instead + */ Empty = 'empty', - /** @deprecated Use `emptyQueue` instead */ + /** + @deprecated Use `emptyQueue` instead + */ ClearFailed = 'clear-failed', } @@ -993,11 +1025,15 @@ export enum SyncRequestType { AlbumsV2 = 'AlbumsV2', AlbumUsersV1 = 'AlbumUsersV1', AlbumToAssetsV1 = 'AlbumToAssetsV1', - /** @deprecated */ + /** + @deprecated + */ AlbumAssetsV1 = 'AlbumAssetsV1', AlbumAssetsV2 = 'AlbumAssetsV2', AlbumAssetExifsV1 = 'AlbumAssetExifsV1', - /** @deprecated */ + /** + @deprecated + */ AssetsV1 = 'AssetsV1', AssetsV2 = 'AssetsV2', AssetExifsV1 = 'AssetExifsV1', @@ -1008,7 +1044,9 @@ export enum SyncRequestType { MemoriesV1 = 'MemoriesV1', MemoryToAssetsV1 = 'MemoryToAssetsV1', PartnersV1 = 'PartnersV1', - /** @deprecated */ + /** + @deprecated + */ PartnerAssetsV1 = 'PartnerAssetsV1', PartnerAssetsV2 = 'PartnerAssetsV2', PartnerAssetExifsV1 = 'PartnerAssetExifsV1', @@ -1016,7 +1054,9 @@ export enum SyncRequestType { StacksV1 = 'StacksV1', UsersV1 = 'UsersV1', PeopleV1 = 'PeopleV1', - /** @deprecated */ + /** + @deprecated + */ AssetFacesV1 = 'AssetFacesV1', AssetFacesV2 = 'AssetFacesV2', UserMetadataV1 = 'UserMetadataV1', @@ -1033,7 +1073,9 @@ export enum SyncEntityType { UserV1 = 'UserV1', UserDeleteV1 = 'UserDeleteV1', - /** @deprecated */ + /** + @deprecated + */ AssetV1 = 'AssetV1', AssetV2 = 'AssetV2', AssetDeleteV1 = 'AssetDeleteV1', @@ -1048,10 +1090,14 @@ export enum SyncEntityType { PartnerV1 = 'PartnerV1', PartnerDeleteV1 = 'PartnerDeleteV1', - /** @deprecated */ + /** + @deprecated + */ PartnerAssetV1 = 'PartnerAssetV1', PartnerAssetV2 = 'PartnerAssetV2', - /** @deprecated */ + /** + @deprecated + */ PartnerAssetBackfillV1 = 'PartnerAssetBackfillV1', PartnerAssetBackfillV2 = 'PartnerAssetBackfillV2', PartnerAssetDeleteV1 = 'PartnerAssetDeleteV1', @@ -1069,13 +1115,19 @@ export enum SyncEntityType { AlbumUserBackfillV1 = 'AlbumUserBackfillV1', AlbumUserDeleteV1 = 'AlbumUserDeleteV1', - /** @deprecated */ + /** + @deprecated + */ AlbumAssetCreateV1 = 'AlbumAssetCreateV1', AlbumAssetCreateV2 = 'AlbumAssetCreateV2', - /** @deprecated */ + /** + @deprecated + */ AlbumAssetUpdateV1 = 'AlbumAssetUpdateV1', AlbumAssetUpdateV2 = 'AlbumAssetUpdateV2', - /** @deprecated */ + /** + @deprecated + */ AlbumAssetBackfillV1 = 'AlbumAssetBackfillV1', AlbumAssetBackfillV2 = 'AlbumAssetBackfillV2', AlbumAssetExifCreateV1 = 'AlbumAssetExifCreateV1', diff --git a/server/src/middleware/auth.guard.ts b/server/src/middleware/auth.guard.ts index 93bcfe26e..2a1f30220 100644 --- a/server/src/middleware/auth.guard.ts +++ b/server/src/middleware/auth.guard.ts @@ -25,7 +25,9 @@ export type AuthenticatedOptions = AuthorizedRoute | PublicRoute; type ReflectorTarget = Parameters[1]; -/** Resolves the `@Authenticated()` options of a route handler, with the defaults applied. */ +/** +Resolves the `@Authenticated()` options of a route handler, with the defaults applied. +*/ export const getAuthenticatedOptions = (reflector: Reflector, target: ReflectorTarget) => { const options = reflector.getAllAndOverride(MetadataKey.AuthRoute, [target]); return options && { sharedLink: false, admin: false, public: false, setup: false, ...options }; diff --git a/server/src/repositories/event.repository.ts b/server/src/repositories/event.repository.ts index 7fedc4eb3..ab83cdaf0 100644 --- a/server/src/repositories/event.repository.ts +++ b/server/src/repositories/event.repository.ts @@ -56,15 +56,25 @@ type EventMap = { AssetDeleteAll: [{ assetIds: string[]; userId: string }]; AssetRestoreAll: [{ assetIds: string[]; userId: string }]; - /** a worker receives a job and emits this event to run it */ + /** + a worker receives a job and emits this event to run it + */ JobRun: [QueueName, JobItem]; - /** job pre-hook */ + /** + job pre-hook + */ JobStart: [QueueName, JobItem]; - /** job post-hook */ + /** + job post-hook + */ JobComplete: [QueueName, JobItem]; - /** job finishes without error */ + /** + job finishes without error + */ JobSuccess: [JobSuccessEvent]; - /** job finishes with error */ + /** + job finishes with error + */ JobError: [JobErrorEvent]; // queue events @@ -84,9 +94,13 @@ type EventMap = { // user events UserSignup: [{ notify: boolean; id: string; password?: string }]; UserCreate: [UserEvent]; - /** user is soft deleted */ + /** + user is soft deleted + */ UserTrash: [UserEvent]; - /** user is permanently deleted */ + /** + user is permanently deleted + */ UserDelete: [UserEvent]; UserRestore: [UserEvent]; diff --git a/server/src/repositories/job.repository.ts b/server/src/repositories/job.repository.ts index e925bd503..8902556ea 100644 --- a/server/src/repositories/job.repository.ts +++ b/server/src/repositories/job.repository.ts @@ -287,7 +287,9 @@ export class JobRepository { return this.moduleRef.get(getQueueToken(queue), { strict: false }); } - /** @deprecated */ + /** + @deprecated + */ // todo: remove this when asset notifications no longer need it. public async removeJob(name: JobName, jobID: string): Promise { const existingJob = await this.getQueue(this.getQueueName(name)).getJob(jobID); diff --git a/server/src/repositories/media.repository.ts b/server/src/repositories/media.repository.ts index c1e8cfd23..6b9fa757c 100644 --- a/server/src/repositories/media.repository.ts +++ b/server/src/repositories/media.repository.ts @@ -464,7 +464,9 @@ export class MediaRepository { return value ? ((enumObj[pascalCase(value)] as Extract | undefined) ?? null) : null; } - /** Parse a rational like "60000/1001" or "1/600" into `{ num, den }`. */ + /** + Parse a rational like "60000/1001" or "1/600" into `{ num, den }`. + */ private parseRational(value: string | undefined): { num: number; den: number } | null { if (value) { const [num, den = 1] = value.split('/').map(Number); diff --git a/server/src/repositories/search.repository.ts b/server/src/repositories/search.repository.ts index 4bde10f16..8db06f755 100644 --- a/server/src/repositories/search.repository.ts +++ b/server/src/repositories/search.repository.ts @@ -135,7 +135,9 @@ export type AssetSearchBuilderOptions = Omit; - /** unless set to true, will be automatically deleted in the future */ + /** + unless set to true, will be automatically deleted in the future + */ @Column({ type: 'boolean', default: false }) isSaved!: Generated; - /** memories are sorted in ascending order by this value */ + /** + memories are sorted in ascending order by this value + */ @Column({ type: 'timestamp with time zone' }) memoryAt!: Timestamp; - /** when the user last viewed the memory */ + /** + when the user last viewed the memory + */ @Column({ type: 'timestamp with time zone', nullable: true }) seenAt!: Timestamp | null; diff --git a/server/src/services/auth.service.ts b/server/src/services/auth.service.ts index 560381921..379f0d64f 100644 --- a/server/src/services/auth.service.ts +++ b/server/src/services/auth.service.ts @@ -48,7 +48,9 @@ export type ValidateRequest = { metadata: { sharedLinkRoute: boolean; adminRoute: boolean; - /** `false` explicitly means no permission is required, which otherwise defaults to `all` */ + /** + `false` explicitly means no permission is required, which otherwise defaults to `all` + */ permission?: Permission | false; uri: string; }; diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index a95d1f149..983ad62be 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -42,7 +42,9 @@ import { Tasks } from 'src/utils/tasks'; const POSTGRES_INT_MAX = 2_147_483_647; const POSTGRES_INT_MIN = -2_147_483_648; -/** look for a date from these tags (in order) */ +/** +look for a date from these tags (in order) +*/ const EXIF_DATE_TAGS: Array = [ 'SubSecDateTimeOriginal', 'SubSecCreateDate', diff --git a/server/src/types.ts b/server/src/types.ts index d31841ffd..7cb1cd34a 100644 --- a/server/src/types.ts +++ b/server/src/types.ts @@ -105,19 +105,33 @@ export interface AudioStreamInfo { bitrate: number; } -/** Packet-derived video data needed for accurate HLS playlists. */ +/** +Packet-derived video data needed for accurate HLS playlists. +*/ export interface VideoPacketInfo { - /** Sum of source packet duration across all packets (includes discard). */ + /** + Sum of source packet duration across all packets (includes discard). + */ totalDuration: number; - /** Post-discard packet count. */ + /** + Post-discard packet count. + */ packetCount: number; - /** Output CFR frame count at `packetCount / format.duration`. */ + /** + Output CFR frame count at `packetCount / format.duration`. + */ outputFrames: number; - /** All keyframe PTS in source ticks, including pre-roll discard keyframes. */ + /** + All keyframe PTS in source ticks, including pre-roll discard keyframes. + */ keyframePts: number[]; - /** Cumulative packet duration through each keyframe, inclusive. */ + /** + Cumulative packet duration through each keyframe, inclusive. + */ keyframeAccDuration: number[]; - /** Each keyframe's own packet duration (needed for VFR). */ + /** + Each keyframe's own packet duration (needed for VFR). + */ keyframeOwnDuration: number[]; } @@ -210,7 +224,9 @@ export interface IBaseJob { } export interface IDelayedJob extends IBaseJob { - /** The minimum time to wait to execute this job, in milliseconds. */ + /** + The minimum time to wait to execute this job, in milliseconds. + */ delay?: number; } @@ -452,7 +468,9 @@ export interface ExtensionVersion { export interface ImmichFile extends Express.Multer.File { uuid: string; - /** sha1 hash of file */ + /** + sha1 hash of file + */ checksum: Buffer; } @@ -522,7 +540,9 @@ export type SystemFlags = { mountChecks: Record }; export type MaintenanceModeState = { isMaintenanceMode: true; secret: string; action?: SetMaintenanceModeDto } | { isMaintenanceMode: false }; export type MemoriesState = { - /** memories have already been created through this date */ + /** + memories have already been created through this date + */ lastOnThisDayDate: string; }; export type MediaLocation = { location: string }; diff --git a/server/src/utils/asset.util.ts b/server/src/utils/asset.util.ts index 5420e6036..04270781a 100644 --- a/server/src/utils/asset.util.ts +++ b/server/src/utils/asset.util.ts @@ -113,7 +113,9 @@ export const removeAssets = async ( export type PartnerIdOptions = { userId: string; repository: PartnerRepository; - /** only include partners with `inTimeline: true` */ + /** + only include partners with `inTimeline: true` + */ timelineEnabled?: boolean; }; export const getMyPartnerIds = async ({ userId, repository, timelineEnabled }: PartnerIdOptions) => { diff --git a/server/src/utils/database.ts b/server/src/utils/database.ts index 5122b0a9d..74e38fad8 100644 --- a/server/src/utils/database.ts +++ b/server/src/utils/database.ts @@ -391,7 +391,9 @@ export function withEdits(eb: ExpressionBuilder): AliasedEditAction } const joinDeduplicationPlugin = new DeduplicateJoinsPlugin(); -/** TODO: This should only be used for search-related queries, not as a general purpose query builder */ +/** +TODO: This should only be used for search-related queries, not as a general purpose query builder +*/ export function searchAssetBuilderLegacy(kysely: Kysely, options: AssetSearchBuilderOptions) { options.withDeleted ||= !!(options.trashedAfter || options.trashedBefore || options.isOffline); diff --git a/server/src/utils/mime-types.ts b/server/src/utils/mime-types.ts index bb5e7be95..f5a39b473 100644 --- a/server/src/utils/mime-types.ts +++ b/server/src/utils/mime-types.ts @@ -164,7 +164,9 @@ export const mimeTypes = { transparentCapableExtensions.has(getFilenameExtension(filename).toLowerCase()), isRaw: (filename: string) => isType(filename, raw), lookup, - /** return an extension (including a leading `.`) for a mime-type */ + /** + return an extension (including a leading `.`) for a mime-type + */ toExtension, assetType: (filename: string) => { const contentType = lookup(filename); diff --git a/server/src/utils/workflow.ts b/server/src/utils/workflow.ts index a3a9d56c4..a2517381c 100644 --- a/server/src/utils/workflow.ts +++ b/server/src/utils/workflow.ts @@ -12,7 +12,9 @@ export const triggerMap: Record = { export const getWorkflowTriggers = () => Object.entries(triggerMap).map(([trigger, types]) => ({ trigger: trigger as WorkflowTrigger, types })); -/** some types extend other types and have implied compatibility */ +/** +some types extend other types and have implied compatibility +*/ const inferredMap: Record = { [WorkflowType.AssetV1]: [], // [WorkflowType.AssetPersonV1]: [WorkflowType.AssetV1], diff --git a/server/test/fixtures/media.stub.ts b/server/test/fixtures/media.stub.ts index 4421a0980..6f20b0a42 100644 --- a/server/test/fixtures/media.stub.ts +++ b/server/test/fixtures/media.stub.ts @@ -48,7 +48,9 @@ const probeStubDefault: VideoInfo = { audioStreams: probeStubDefaultAudioStream, }; -/** Fixtures in the shape `mediaRepository.probe()` returns (arrays of streams, raw ffprobe format). */ +/** +Fixtures in the shape `mediaRepository.probe()` returns (arrays of streams, raw ffprobe format). +*/ export const videoInfoStub = { noVideoStreams: Object.freeze({ ...probeStubDefault, videoStreams: [] }), noAudioStreams: Object.freeze({ ...probeStubDefault, audioStreams: [] }), diff --git a/server/test/utils.ts b/server/test/utils.ts index e1920a4a7..3bdbe1f5d 100644 --- a/server/test/utils.ts +++ b/server/test/utils.ts @@ -541,10 +541,8 @@ export const mockDuplex = if (error) { duplex.destroy(error as Error); } else if (exitCode === 0) { - /* eslint-disable unicorn/prefer-single-call */ duplex.push(stdout); duplex.push(null); - /* eslint-enable unicorn/prefer-single-call */ } else { duplex.destroy(new Error(`${command} non-zero exit code (${exitCode})\n${stderr}`)); } diff --git a/web/package.json b/web/package.json index ca0274df8..a7f025959 100644 --- a/web/package.json +++ b/web/package.json @@ -98,7 +98,7 @@ "eslint-plugin-better-tailwindcss": "^4.5.0", "eslint-plugin-compat": "^7.0.0", "eslint-plugin-svelte": "^3.12.4", - "eslint-plugin-unicorn": "^72.0.0", + "eslint-plugin-unicorn": "^73.0.0", "factory.ts": "^1.4.1", "globals": "^17.0.0", "happy-dom": "^20.0.0", diff --git a/web/src/lib/actions/focus.ts b/web/src/lib/actions/focus.ts index 3b6049f24..3b2d70dbb 100644 --- a/web/src/lib/actions/focus.ts +++ b/web/src/lib/actions/focus.ts @@ -1,4 +1,6 @@ -/** Focus the given element when it is mounted. */ +/** +Focus the given element when it is mounted. +*/ export const initInput = (element: HTMLInputElement) => { element.focus(); }; diff --git a/web/src/lib/components/album-page/AlbumsList.svelte b/web/src/lib/components/album-page/AlbumsList.svelte index 69ba212c1..318e501b9 100644 --- a/web/src/lib/components/album-page/AlbumsList.svelte +++ b/web/src/lib/components/album-page/AlbumsList.svelte @@ -55,7 +55,9 @@ } const groupOptions: AlbumGroupOption = { - /** No grouping */ + /** + No grouping + */ [AlbumGroupBy.None]: (order, albums): AlbumGroup[] => { return [ { @@ -66,7 +68,9 @@ ]; }, - /** Group by year */ + /** + Group by year + */ [AlbumGroupBy.Year]: (order, albums): AlbumGroup[] => { const unknownYear = $t('unknown_year'); const useStartDate = userSettings.sortBy === AlbumSortBy.OldestPhoto; @@ -92,7 +96,9 @@ })); }, - /** Group by owner */ + /** + Group by owner + */ [AlbumGroupBy.Owner]: (order, albums): AlbumGroup[] => { const currentUserId = authManager.user.id; const groupedByOwnerIds = groupBy(albums, (album) => album.albumUsers[0].user.id); diff --git a/web/src/lib/components/asset-viewer/PhotoSphereViewerAdapter.svelte b/web/src/lib/components/asset-viewer/PhotoSphereViewerAdapter.svelte index a98418d65..76dedff6c 100644 --- a/web/src/lib/components/asset-viewer/PhotoSphereViewerAdapter.svelte +++ b/web/src/lib/components/asset-viewer/PhotoSphereViewerAdapter.svelte @@ -108,7 +108,9 @@ updateOcrBoxes(ocrManager.showOverlay, ocrManager.data); }); - /** Use updateOnly=true on zoom, pan, or resize. */ + /** + Use updateOnly=true on zoom, pan, or resize. + */ const updateOcrBoxes = (showOverlay: boolean, ocrData: OcrBoundingBox[], updateOnly = false) => { if (!viewer || !viewer.state.textureData || !viewer.getPlugin(MarkersPlugin)) { return; diff --git a/web/src/lib/components/timeline/Scrubber.svelte b/web/src/lib/components/timeline/Scrubber.svelte index 67ec87ff7..bdac1823d 100644 --- a/web/src/lib/components/timeline/Scrubber.svelte +++ b/web/src/lib/components/timeline/Scrubber.svelte @@ -11,30 +11,54 @@ import { fade, fly } from 'svelte/transition'; interface Props { - /** Offset from the top of the timeline (e.g., for headers) */ + /** + Offset from the top of the timeline (e.g., for headers) + */ timelineTopOffset?: number; - /** Offset from the bottom of the timeline (e.g., for footers) */ + /** + Offset from the bottom of the timeline (e.g., for footers) + */ timelineBottomOffset?: number; - /** Total height of the scrubber component */ + /** + Total height of the scrubber component + */ height?: number; - /** Timeline manager instance that controls the timeline state */ + /** + Timeline manager instance that controls the timeline state + */ timelineManager: TimelineManager; - /** Overall scroll percentage through the entire timeline (0-1), used when no specific month is targeted */ + /** + Overall scroll percentage through the entire timeline (0-1), used when no specific month is targeted + */ timelineScrollPercent?: number; - /** The percentage of scroll through the month that is currently intersecting the top boundary of the viewport */ + /** + The percentage of scroll through the month that is currently intersecting the top boundary of the viewport + */ viewportTopMonthScrollPercent?: number; - /** The year/month of the timeline month at the top of the viewport */ + /** + The year/month of the timeline month at the top of the viewport + */ viewportTopMonth?: ViewportTopMonth; - /** Width of the scrubber component in pixels (bindable for parent component margin adjustments) */ + /** + Width of the scrubber component in pixels (bindable for parent component margin adjustments) + */ scrubberWidth?: number; - /** Callback fired when user interacts with the scrubber to navigate */ + /** + Callback fired when user interacts with the scrubber to navigate + */ onScrub?: ScrubberListener; - /** Callback fired when keyboard events occur on the scrubber */ + /** + Callback fired when keyboard events occur on the scrubber + */ onScrubKeyDown?: (event: KeyboardEvent, element: HTMLElement) => void; - /** Callback fired when scrubbing starts */ + /** + Callback fired when scrubbing starts + */ startScrub?: ScrubberListener; - /** Callback fired when scrubbing stops */ + /** + Callback fired when scrubbing stops + */ stopScrub?: ScrubberListener; } diff --git a/web/src/lib/utils/album-utils.ts b/web/src/lib/utils/album-utils.ts index 97546f0b0..cfd090818 100644 --- a/web/src/lib/utils/album-utils.ts +++ b/web/src/lib/utils/album-utils.ts @@ -223,34 +223,46 @@ export const stringToSortOrder = (order: string) => { }; const sortOptions: AlbumSortOption = { - /** Sort by album title */ + /** + Sort by album title + */ [AlbumSortBy.Title]: (order, albums) => { const sortSign = order === SortOrder.Desc ? -1 : 1; return albums.slice().sort((a, b) => a.albumName.localeCompare(b.albumName, get(locale)) * sortSign); }, - /** Sort by asset count */ + /** + Sort by asset count + */ [AlbumSortBy.ItemCount]: (order, albums) => { return orderBy(albums, 'assetCount', [order]); }, - /** Sort by last modified */ + /** + Sort by last modified + */ [AlbumSortBy.DateModified]: (order, albums) => { return orderBy(albums, [({ updatedAt }) => new Date(updatedAt)], [order]); }, - /** Sort by creation date */ + /** + Sort by creation date + */ [AlbumSortBy.DateCreated]: (order, albums) => { return orderBy(albums, [({ createdAt }) => new Date(createdAt)], [order]); }, - /** Sort by the most recent photo date */ + /** + Sort by the most recent photo date + */ [AlbumSortBy.MostRecentPhoto]: (order, albums) => { albums = orderBy(albums, [({ endDate }) => (endDate ? new Date(endDate) : '')], [order]); return albums.sort(sortUnknownYearAlbums); }, - /** Sort by the oldest photo date */ + /** + Sort by the oldest photo date + */ [AlbumSortBy.OldestPhoto]: (order, albums) => { albums = orderBy(albums, [({ startDate }) => (startDate ? new Date(startDate) : '')], [order]); return albums.sort(sortUnknownYearAlbums); diff --git a/web/src/lib/utils/invocationTracker.ts b/web/src/lib/utils/invocationTracker.ts index ada3b12d0..9f2501be8 100644 --- a/web/src/lib/utils/invocationTracker.ts +++ b/web/src/lib/utils/invocationTracker.ts @@ -6,9 +6,13 @@ import { handleError } from '$lib/utils/handle-error'; * and allowing operations to check if they're still valid. */ export class InvocationTracker { - /** Counter for the number of invocations that have been started */ + /** + Counter for the number of invocations that have been started + */ invocationsStarted = 0; - /** Counter for the number of invocations that have been completed */ + /** + Counter for the number of invocations that have been completed + */ invocationsEnded = 0; constructor() {} diff --git a/web/src/lib/utils/navigation.ts b/web/src/lib/utils/navigation.ts index 9bba61d91..22678fd5f 100644 --- a/web/src/lib/utils/navigation.ts +++ b/web/src/lib/utils/navigation.ts @@ -92,7 +92,9 @@ interface AssetGridRoute extends Route { type ImmichRoute = AssetRoute | AssetGridRoute; type NavOptions = { - /* navigate even if url is the same */ + /* + navigate even if url is the same + */ forceNavigate?: boolean | undefined; replaceState?: boolean | undefined; noScroll?: boolean | undefined; diff --git a/web/src/params/id.ts b/web/src/params/id.ts index 440d4532a..73e8eec86 100644 --- a/web/src/params/id.ts +++ b/web/src/params/id.ts @@ -1,7 +1,9 @@ import type { ParamMatcher } from '@sveltejs/kit'; import { UUID_REGEX } from '$lib/constants'; -/* Returns true if the given param matches UUID format */ +/* +Returns true if the given param matches UUID format +*/ export const match: ParamMatcher = (param: string) => { return UUID_REGEX.test(param); }; diff --git a/web/src/routes/(user)/places/PlacesList.svelte b/web/src/routes/(user)/places/PlacesList.svelte index 2f2dfed9c..7ac9b287b 100644 --- a/web/src/routes/(user)/places/PlacesList.svelte +++ b/web/src/routes/(user)/places/PlacesList.svelte @@ -33,7 +33,9 @@ } const groupOptions: PlacesGroupOption = { - /** No grouping */ + /** + No grouping + */ [PlacesGroupBy.None]: (places): PlacesGroup[] => { return [ { @@ -44,7 +46,9 @@ ]; }, - /** Group by year */ + /** + Group by year + */ [PlacesGroupBy.Country]: (places): PlacesGroup[] => { const unknownCountry = $t('unknown_country');