feat: NestJS 12 and ESM (#31237)

This commit is contained in:
Daniel Dietzler
2026-09-10 13:22:29 +02:00
committed by GitHub
parent c5fea7f32b
commit 2a62622041
626 changed files with 4558 additions and 4817 deletions
@@ -1,6 +1,6 @@
import { LoginResponseDto, ManualJobName } from '@immich/sdk';
import { errorDto } from 'src/responses';
import { app, utils } from 'src/utils';
import { errorDto } from 'src/responses.js';
import { app, utils } from 'src/utils.js';
import request from 'supertest';
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
@@ -1,6 +1,6 @@
import { LoginResponseDto } from '@immich/sdk';
import { errorDto } from 'src/responses';
import { app, utils } from 'src/utils';
import { errorDto } from 'src/responses.js';
import { app, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, describe, expect, it } from 'vitest';
@@ -1,6 +1,6 @@
import { LoginResponseDto } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import { utils } from 'src/utils';
import { utils } from 'src/utils.js';
test.describe.configure({ mode: 'serial' });
@@ -1,6 +1,6 @@
import { LoginResponseDto } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import { utils } from 'src/utils';
import { utils } from 'src/utils.js';
test.describe.configure({ mode: 'serial' });
+3 -3
View File
@@ -9,9 +9,9 @@ import {
LoginResponseDto,
SharedLinkType,
} from '@immich/sdk';
import { createUserDto } from 'src/fixtures';
import { errorDto } from 'src/responses';
import { app, asBearerAuth, utils } from 'src/utils';
import { createUserDto } from 'src/fixtures.js';
import { errorDto } from 'src/responses.js';
import { app, asBearerAuth, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
+3 -3
View File
@@ -1,7 +1,7 @@
import { LoginResponseDto, Permission, createApiKey } from '@immich/sdk';
import { createUserDto } from 'src/fixtures';
import { errorDto } from 'src/responses';
import { app, asBearerAuth, utils } from 'src/utils';
import { createUserDto } from 'src/fixtures.js';
import { errorDto } from 'src/responses.js';
import { app, asBearerAuth, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
+4 -4
View File
@@ -14,10 +14,10 @@ import { randomBytes } from 'node:crypto';
import { readFile, writeFile } from 'node:fs/promises';
import { basename, join } from 'node:path';
import { Socket } from 'socket.io-client';
import { createUserDto, uuidDto } from 'src/fixtures';
import { makeRandomImage } from 'src/generators';
import { errorDto } from 'src/responses';
import { app, asBearerAuth, tempDir, testAssetDir, utils } from 'src/utils';
import { createUserDto, uuidDto } from 'src/fixtures.js';
import { makeRandomImage } from 'src/generators.js';
import { errorDto } from 'src/responses.js';
import { app, asBearerAuth, tempDir, testAssetDir, utils } from 'src/utils.js';
import request from 'supertest';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
@@ -1,6 +1,6 @@
import { AssetMediaResponseDto, LoginResponseDto } from '@immich/sdk';
import { readFile, writeFile } from 'node:fs/promises';
import { app, tempDir, utils } from 'src/utils';
import { app, tempDir, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, describe, expect, it } from 'vitest';
@@ -7,7 +7,7 @@ import {
QueueName,
} from '@immich/sdk';
import { readFile } from 'node:fs/promises';
import { app, testAssetDir, utils } from 'src/utils';
import { app, testAssetDir, utils } from 'src/utils.js';
import request from 'supertest';
import { afterEach, beforeAll, describe, expect, it } from 'vitest';
+1 -1
View File
@@ -2,7 +2,7 @@ import { LoginResponseDto, QueueCommand, QueueName, updateConfig } from '@immich
import { cpSync, rmSync } from 'node:fs';
import { readFile } from 'node:fs/promises';
import { basename } from 'node:path';
import { asBearerAuth, testAssetDir, utils } from 'src/utils';
import { asBearerAuth, testAssetDir, utils } from 'src/utils.js';
import { afterEach, beforeAll, describe, expect, it } from 'vitest';
describe('/jobs', () => {
+1 -1
View File
@@ -1,7 +1,7 @@
import { LoginResponseDto } from '@immich/sdk';
import { cpSync } from 'node:fs';
import { Socket } from 'socket.io-client';
import { testAssetDir, testAssetDirInternal, utils } from 'src/utils';
import { testAssetDir, testAssetDirInternal, utils } from 'src/utils.js';
import { utimes } from 'utimes';
import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
+2 -2
View File
@@ -2,8 +2,8 @@ import { AssetVisibility, LoginResponseDto } from '@immich/sdk';
import { readFile } from 'node:fs/promises';
import { basename, join } from 'node:path';
import { Socket } from 'socket.io-client';
import { createUserDto } from 'src/fixtures';
import { app, testAssetDir, utils } from 'src/utils';
import { createUserDto } from 'src/fixtures.js';
import { app, testAssetDir, utils } from 'src/utils.js';
import request from 'supertest';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
+2 -2
View File
@@ -9,8 +9,8 @@ import {
updateConfig,
} from '@immich/sdk';
import { createHash, randomBytes } from 'node:crypto';
import { errorDto } from 'src/responses';
import { app, asBearerAuth, baseUrl, utils } from 'src/utils';
import { errorDto } from 'src/responses.js';
import { app, asBearerAuth, baseUrl, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, describe, expect, it } from 'vitest';
+3 -3
View File
@@ -1,7 +1,7 @@
import { getPerson, LoginResponseDto, PersonResponseDto } from '@immich/sdk';
import { uuidDto } from 'src/fixtures';
import { errorDto } from 'src/responses';
import { app, asBearerAuth, utils } from 'src/utils';
import { uuidDto } from 'src/fixtures.js';
import { errorDto } from 'src/responses.js';
import { app, asBearerAuth, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
+1 -1
View File
@@ -11,7 +11,7 @@ import { DateTime } from 'luxon';
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { Socket } from 'socket.io-client';
import { app, asBearerAuth, TEN_TIMES, testAssetDir, utils } from 'src/utils';
import { app, asBearerAuth, TEN_TIMES, testAssetDir, utils } from 'src/utils.js';
import request from 'supertest';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
const today = DateTime.now();
+2 -2
View File
@@ -1,6 +1,6 @@
import { LoginResponseDto } from '@immich/sdk';
import { createUserDto } from 'src/fixtures';
import { app, utils } from 'src/utils';
import { createUserDto } from 'src/fixtures.js';
import { app, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, describe, expect, it } from 'vitest';
+3 -3
View File
@@ -1,7 +1,7 @@
import { LoginResponseDto, getSessions, login, signUpAdmin } from '@immich/sdk';
import { loginDto, signupDto, uuidDto } from 'src/fixtures';
import { errorDto } from 'src/responses';
import { app, asBearerAuth, utils } from 'src/utils';
import { loginDto, signupDto, uuidDto } from 'src/fixtures.js';
import { errorDto } from 'src/responses.js';
import { app, asBearerAuth, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeEach, describe, expect, it } from 'vitest';
@@ -7,9 +7,9 @@ import {
createAlbum,
deleteUserAdmin,
} from '@immich/sdk';
import { createUserDto, uuidDto } from 'src/fixtures';
import { errorDto } from 'src/responses';
import { app, asBearerAuth, baseUrl, shareUrl, utils } from 'src/utils';
import { createUserDto, uuidDto } from 'src/fixtures.js';
import { errorDto } from 'src/responses.js';
import { app, asBearerAuth, baseUrl, shareUrl, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, describe, expect, it } from 'vitest';
+2 -2
View File
@@ -1,6 +1,6 @@
import { LoginResponseDto, searchStacks } from '@immich/sdk';
import { createUserDto } from 'src/fixtures';
import { app, asBearerAuth, utils } from 'src/utils';
import { createUserDto } from 'src/fixtures.js';
import { app, asBearerAuth, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, describe, expect, it } from 'vitest';
@@ -1,6 +1,6 @@
import { LoginResponseDto, getConfig } from '@immich/sdk';
import { errorDto } from 'src/responses';
import { app, asBearerAuth, utils } from 'src/utils';
import { errorDto } from 'src/responses.js';
import { app, asBearerAuth, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, describe, expect, it } from 'vitest';
@@ -1,5 +1,5 @@
import { LoginResponseDto, getServerConfig } from '@immich/sdk';
import { app, utils } from 'src/utils';
import { app, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, describe, expect, it } from 'vitest';
+3 -3
View File
@@ -9,9 +9,9 @@ import {
tagAssets,
upsertTags,
} from '@immich/sdk';
import { createUserDto } from 'src/fixtures';
import { errorDto } from 'src/responses';
import { app, asBearerAuth, utils } from 'src/utils';
import { createUserDto } from 'src/fixtures.js';
import { errorDto } from 'src/responses.js';
import { app, asBearerAuth, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
+1 -1
View File
@@ -1,7 +1,7 @@
import { LoginResponseDto, getAssetInfo, getAssetStatistics } from '@immich/sdk';
import { existsSync } from 'node:fs';
import { Socket } from 'socket.io-client';
import { app, asBearerAuth, testAssetDir, testAssetDirInternal, utils } from 'src/utils';
import { app, asBearerAuth, testAssetDir, testAssetDirInternal, utils } from 'src/utils.js';
import request from 'supertest';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
@@ -9,8 +9,8 @@ import {
login,
} from '@immich/sdk';
import { Socket } from 'socket.io-client';
import { createUserDto } from 'src/fixtures';
import { app, asBearerAuth, utils } from 'src/utils';
import { createUserDto } from 'src/fixtures.js';
import { app, asBearerAuth, utils } from 'src/utils.js';
import request from 'supertest';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
+2 -2
View File
@@ -1,6 +1,6 @@
import { LoginResponseDto, getMyUser, login } from '@immich/sdk';
import { createUserDto } from 'src/fixtures';
import { app, asBearerAuth, utils } from 'src/utils';
import { createUserDto } from 'src/fixtures.js';
import { app, asBearerAuth, utils } from 'src/utils.js';
import request from 'supertest';
import { beforeAll, describe, expect, it } from 'vitest';
+1 -1
View File
@@ -1,6 +1,6 @@
import { Permission } from '@immich/sdk';
import { stat } from 'node:fs/promises';
import { app, immichCli, utils } from 'src/utils';
import { app, immichCli, utils } from 'src/utils.js';
import { beforeEach, describe, expect, it } from 'vitest';
describe(`immich login`, () => {
@@ -1,4 +1,4 @@
import { immichCli, utils } from 'src/utils';
import { immichCli, utils } from 'src/utils.js';
import { beforeAll, describe, expect, it } from 'vitest';
describe(`immich server-info`, () => {
+1 -1
View File
@@ -1,7 +1,7 @@
import { LoginResponseDto, getAllAlbums, getAssetStatistics } from '@immich/sdk';
import { cpSync, readFileSync } from 'node:fs';
import { mkdir, readdir, rm, symlink } from 'node:fs/promises';
import { asKeyAuth, immichCli, specialCharStrings, testAssetDir, utils } from 'src/utils';
import { asKeyAuth, immichCli, specialCharStrings, testAssetDir, utils } from 'src/utils.js';
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
interface Test {
+1 -1
View File
@@ -1,5 +1,5 @@
import { readFileSync } from 'node:fs';
import { immichCli } from 'src/utils';
import { immichCli } from 'src/utils.js';
import { describe, expect, it } from 'vitest';
const pkg = JSON.parse(readFileSync('../packages/cli/package.json', 'utf8'));
@@ -1,4 +1,4 @@
import { immichAdmin, utils } from 'src/utils';
import { immichAdmin, utils } from 'src/utils.js';
import { beforeAll, describe, expect, it } from 'vitest';
describe(`immich-admin`, () => {
+1 -1
View File
@@ -1,7 +1,7 @@
import { LoginResponseDto } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import { readFileSync } from 'node:fs';
import { testAssetDir, utils } from 'src/utils';
import { testAssetDir, utils } from 'src/utils.js';
test.describe('Album', () => {
let admin: LoginResponseDto;
@@ -3,7 +3,7 @@ import { expect, test } from '@playwright/test';
import { readFile } from 'node:fs/promises';
import { basename, join } from 'node:path';
import type { Socket } from 'socket.io-client';
import { testAssetDir, utils } from 'src/utils';
import { testAssetDir, utils } from 'src/utils.js';
test.describe('Detail Panel', () => {
let admin: LoginResponseDto;
@@ -1,6 +1,6 @@
import { AssetMediaResponseDto, LoginResponseDto, SharedLinkType } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import { utils } from 'src/utils';
import { utils } from 'src/utils.js';
test.describe('Asset Viewer Navbar', () => {
let admin: LoginResponseDto;
@@ -1,6 +1,6 @@
import { AssetMediaResponseDto, LoginResponseDto } from '@immich/sdk';
import { expect, type Page, test } from '@playwright/test';
import { utils } from 'src/utils';
import { utils } from 'src/utils.js';
test.describe('Slideshow', () => {
let admin: LoginResponseDto;
+1 -1
View File
@@ -1,5 +1,5 @@
import { expect, test } from '@playwright/test';
import { utils } from 'src/utils';
import { utils } from 'src/utils.js';
test.describe('Registration', () => {
test.beforeAll(() => {
+1 -1
View File
@@ -1,7 +1,7 @@
import { AssetMediaResponseDto, LoginResponseDto, updateAssets } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import crypto from 'node:crypto';
import { asBearerAuth, utils } from 'src/utils';
import { asBearerAuth, utils } from 'src/utils.js';
test.describe('Duplicates Utility', () => {
let admin: LoginResponseDto;
+1 -1
View File
@@ -1,6 +1,6 @@
import { LoginResponseDto, ManualJobName, QueueName } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import { utils } from 'src/utils';
import { utils } from 'src/utils.js';
test.describe.configure({ mode: 'serial' });
+1 -1
View File
@@ -1,7 +1,7 @@
import { AssetMediaResponseDto, LoginResponseDto } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import type { Socket } from 'socket.io-client';
import { utils } from 'src/utils';
import { utils } from 'src/utils.js';
test.describe('Photo Viewer', () => {
let admin: LoginResponseDto;
+1 -1
View File
@@ -7,7 +7,7 @@ import {
createAlbum,
} from '@immich/sdk';
import { expect, test } from '@playwright/test';
import { asBearerAuth, utils } from 'src/utils';
import { asBearerAuth, utils } from 'src/utils.js';
test.describe('Shared Links', () => {
let admin: LoginResponseDto;
+1 -1
View File
@@ -1,6 +1,6 @@
import { getUserAdmin } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import { asBearerAuth, utils } from 'src/utils';
import { asBearerAuth, utils } from 'src/utils.js';
test.describe('User Administration', () => {
test.beforeAll(() => {
+1 -1
View File
@@ -1,6 +1,6 @@
import { LoginResponseDto } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import { utils } from 'src/utils';
import { utils } from 'src/utils.js';
test.describe('Websocket', () => {
let admin: LoginResponseDto;
@@ -1,9 +1,9 @@
import { faker } from '@faker-js/faker';
import { MemoryType, type MemoryResponseDto, type OnThisDayDto } from '@immich/sdk';
import { DateTime } from 'luxon';
import { toAssetResponseDto } from 'src/ui/generators/timeline/rest-response';
import type { MockTimelineAsset } from 'src/ui/generators/timeline/timeline-config';
import { SeededRandom, selectRandomMultiple } from 'src/ui/generators/timeline/utils';
import { toAssetResponseDto } from 'src/ui/generators/timeline/rest-response.js';
import type { MockTimelineAsset } from 'src/ui/generators/timeline/timeline-config.js';
import { SeededRandom, selectRandomMultiple } from 'src/ui/generators/timeline/utils.js';
export type MemoryConfig = {
id?: string;
@@ -1,5 +1,5 @@
import { generateConsecutiveDays, generateDayAssets } from 'src/ui/generators/timeline/model-objects';
import { SeededRandom, selectRandomDays } from 'src/ui/generators/timeline/utils';
import { generateConsecutiveDays, generateDayAssets } from 'src/ui/generators/timeline/model-objects.js';
import { SeededRandom, selectRandomDays } from 'src/ui/generators/timeline/utils.js';
import type { MockTimelineAsset } from './timeline-config';
import { GENERATION_CONSTANTS } from './timeline-config';
+1 -1
View File
@@ -1,5 +1,5 @@
import sharp from 'sharp';
import { SeededRandom } from 'src/ui/generators/timeline/utils';
import { SeededRandom } from 'src/ui/generators/timeline/utils.js';
export const randomThumbnail = async (seed: string, ratio: number) => {
const height = 235;
@@ -6,7 +6,7 @@ import { faker } from '@faker-js/faker';
import { AssetVisibility } from '@immich/sdk';
import { DateTime } from 'luxon';
import { writeFileSync } from 'node:fs';
import { SeededRandom } from 'src/ui/generators/timeline/utils';
import { SeededRandom } from 'src/ui/generators/timeline/utils.js';
import type { DayPattern, MonthDistribution } from './distribution-patterns';
import { ASSET_DISTRIBUTION, DAY_DISTRIBUTION } from './distribution-patterns';
import type { MockTimelineAsset, MockTimelineData, SerializedTimelineData, TimelineConfig } from './timeline-config';
@@ -15,8 +15,8 @@ import {
type UserResponseDto,
} from '@immich/sdk';
import { DateTime } from 'luxon';
import { signupDto } from 'src/fixtures';
import { parseTimeBucketKey } from 'src/ui/generators/timeline/utils';
import { signupDto } from 'src/fixtures.js';
import { parseTimeBucketKey } from 'src/ui/generators/timeline/utils.js';
import type { MockTimelineAsset, MockTimelineData } from './timeline-config';
/**
@@ -1,5 +1,5 @@
import type { AssetVisibility } from '@immich/sdk';
import { DayPattern, MonthDistribution } from 'src/ui/generators/timeline/distribution-patterns';
import { DayPattern, MonthDistribution } from 'src/ui/generators/timeline/distribution-patterns.js';
// Constants for generation parameters
export const GENERATION_CONSTANTS = {
+1 -1
View File
@@ -1,5 +1,5 @@
import { DateTime } from 'luxon';
import { GENERATION_CONSTANTS, MockTimelineAsset } from 'src/ui/generators/timeline/timeline-config';
import { GENERATION_CONSTANTS, MockTimelineAsset } from 'src/ui/generators/timeline/timeline-config.js';
/**
* Linear Congruential Generator for deterministic pseudo-random numbers
+1 -1
View File
@@ -1,5 +1,5 @@
import { BrowserContext } from '@playwright/test';
import { playwrightHost } from 'src/../playwright.config';
import { playwrightHost } from 'src/../playwright.config.js';
export const setupBaseMockApiRoutes = async (context: BrowserContext, adminUserId: string) => {
await context.addCookies([
@@ -1,7 +1,7 @@
import { faker } from '@faker-js/faker';
import { AssetTypeEnum, AssetVisibility, type AssetResponseDto, type StackResponseDto } from '@immich/sdk';
import { BrowserContext } from '@playwright/test';
import { randomPreview, randomThumbnail } from 'src/ui/generators/timeline';
import { randomPreview, randomThumbnail } from 'src/ui/generators/timeline.js';
export type MockStack = {
id: string;
@@ -1,5 +1,5 @@
import { BrowserContext } from '@playwright/test';
import { randomThumbnail } from 'src/ui/generators/timeline';
import { randomThumbnail } from 'src/ui/generators/timeline.js';
// Minimal valid H.264 MP4 (8x8px, 1 frame) that browsers can decode to get videoWidth/videoHeight
const MINIMAL_MP4_BASE64 =
+1 -1
View File
@@ -11,7 +11,7 @@ import {
randomThumbnail,
TimelineData,
} from 'src/ui/generators/timeline';
import { sleep } from 'src/ui/specs/timeline/utils';
import { sleep } from 'src/ui/specs/timeline/utils.js';
import { MINIMAL_MP4_BUFFER } from './face-editor-network';
export class TimelineTestContext {
@@ -9,9 +9,9 @@ import {
TimelineAssetConfig,
TimelineData,
} from 'src/ui/generators/timeline';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/ui/mock-network/timeline-network';
import { utils } from 'src/utils';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network.js';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/ui/mock-network/timeline-network.js';
import { utils } from 'src/utils.js';
import { assetViewerUtils } from '../timeline/utils';
test.describe.configure({ mode: 'parallel' });
@@ -1,5 +1,5 @@
import { expect, test } from '@playwright/test';
import { toAssetResponseDto } from 'src/ui/generators/timeline';
import { toAssetResponseDto } from 'src/ui/generators/timeline.js';
import {
createMockStack,
createMockStackAsset,
@@ -1,5 +1,5 @@
import { expect, Page, test } from '@playwright/test';
import { SeededRandom, selectRandom, TimelineAssetConfig } from 'src/ui/generators/timeline';
import { SeededRandom, selectRandom, TimelineAssetConfig } from 'src/ui/generators/timeline.js';
import {
createMockPeople,
FaceCreateCapture,
@@ -1,13 +1,13 @@
import type { AssetOcrResponseDto, AssetResponseDto } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import { toAssetResponseDto } from 'src/ui/generators/timeline';
import { toAssetResponseDto } from 'src/ui/generators/timeline.js';
import {
createMockStack,
createMockStackAsset,
MockStack,
setupBrokenAssetMockApiRoutes,
} from 'src/ui/mock-network/broken-asset-network';
import { createMockOcrData, setupOcrMockApiRoutes } from 'src/ui/mock-network/ocr-network';
import { createMockOcrData, setupOcrMockApiRoutes } from 'src/ui/mock-network/ocr-network.js';
import { assetViewerUtils } from '../timeline/utils';
import { setupAssetViewerFixture } from './utils';
@@ -1,7 +1,7 @@
import { faker } from '@faker-js/faker';
import type { AssetResponseDto } from '@immich/sdk';
import { expect, test } from '@playwright/test';
import { toAssetResponseDto } from 'src/ui/generators/timeline';
import { toAssetResponseDto } from 'src/ui/generators/timeline.js';
import {
createMockStack,
createMockStackAsset,
+3 -3
View File
@@ -11,9 +11,9 @@ import {
TimelineData,
toAssetResponseDto,
} from 'src/ui/generators/timeline';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/ui/mock-network/timeline-network';
import { utils } from 'src/utils';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network.js';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/ui/mock-network/timeline-network.js';
import { utils } from 'src/utils.js';
export type AssetViewerTestFixture = {
adminUserId: string;
@@ -1,7 +1,7 @@
import { faker } from '@faker-js/faker';
import type { MemoryResponseDto } from '@immich/sdk';
import { test } from '@playwright/test';
import { generateMemoriesFromTimeline } from 'src/ui/generators/memory';
import { generateMemoriesFromTimeline } from 'src/ui/generators/memory.js';
import {
Changes,
createDefaultTimelineConfig,
@@ -9,9 +9,9 @@ import {
TimelineAssetConfig,
TimelineData,
} from 'src/ui/generators/timeline';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network';
import { MemoryChanges, setupMemoryMockApiRoutes } from 'src/ui/mock-network/memory-network';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/ui/mock-network/timeline-network';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network.js';
import { MemoryChanges, setupMemoryMockApiRoutes } from 'src/ui/mock-network/memory-network.js';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/ui/mock-network/timeline-network.js';
import { memoryAssetViewerUtils, memoryGalleryUtils, memoryViewerUtils } from './utils';
test.describe.configure({ mode: 'parallel' });
@@ -8,8 +8,8 @@ import {
TimelineData,
toAssetResponseDto,
} from 'src/ui/generators/timeline';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/ui/mock-network/timeline-network';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network.js';
import { setupTimelineMockApiRoutes, TimelineTestContext } from 'src/ui/mock-network/timeline-network.js';
import { assetViewerUtils } from '../timeline/utils';
const buildSearchUrl = (assetId: string) => {
@@ -13,13 +13,13 @@ import {
TimelineAssetConfig,
TimelineData,
} from 'src/ui/generators/timeline';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network';
import { setupBaseMockApiRoutes } from 'src/ui/mock-network/base-network.js';
import {
pageRoutePromise,
setupTimelineMockApiRoutes,
TimelineTestContext,
} from 'src/ui/mock-network/timeline-network';
import { utils } from 'src/utils';
import { utils } from 'src/utils.js';
import { assetViewerUtils, padYearMonth, pageUtils, poll, thumbnailUtils, timelineUtils } from './utils';
test.describe.configure({ mode: 'parallel' });
+1 -1
View File
@@ -1,6 +1,6 @@
import { expect, Page } from '@playwright/test';
import { DateTime } from 'luxon';
import { TimelineAssetConfig } from 'src/ui/generators/timeline';
import { TimelineAssetConfig } from 'src/ui/generators/timeline.js';
export const sleep = (ms: number) => {
return new Promise((resolve) => setTimeout(resolve, ms));
+2 -2
View File
@@ -67,8 +67,8 @@ import { promisify } from 'node:util';
import { createGzip } from 'node:zlib';
import pg from 'pg';
import { io, type Socket } from 'socket.io-client';
import { loginDto, signupDto } from 'src/fixtures';
import { makeRandomImage } from 'src/generators';
import { loginDto, signupDto } from 'src/fixtures.js';
import { makeRandomImage } from 'src/generators.js';
import request from 'supertest';
import { playwrightDbHost, playwrightHost, playwriteBaseUrl } from '../playwright.config';
+2 -2
View File
@@ -21,8 +21,8 @@ import micromatch from 'micromatch';
import { Stats, createReadStream, existsSync } from 'node:fs';
import { stat, unlink } from 'node:fs/promises';
import path, { basename } from 'node:path';
import { Queue } from 'src/queue';
import { BaseOptions, Batcher, authenticate, crawl, requirePermissions, s, sha1 } from 'src/utils';
import { Queue } from 'src/queue.js';
import { BaseOptions, Batcher, authenticate, crawl, requirePermissions, s, sha1 } from 'src/utils.js';
const UPLOAD_WATCH_BATCH_SIZE = 100;
const UPLOAD_WATCH_DEBOUNCE_TIME_MS = 10_000;
+1 -1
View File
@@ -1,5 +1,5 @@
import { getAssetStatistics, getMyUser, getServerVersion, getSupportedMediaTypes, Permission } from '@immich/sdk';
import { authenticate, BaseOptions, requirePermissions } from 'src/utils';
import { authenticate, BaseOptions, requirePermissions } from 'src/utils.js';
export const serverInfo = async (options: BaseOptions) => {
const { url } = await authenticate(options);
+3 -3
View File
@@ -3,9 +3,9 @@ import { AssetVisibility } from '@immich/sdk';
import { Command, Option } from 'commander';
import os from 'node:os';
import path from 'node:path';
import { upload } from 'src/commands/asset';
import { login, logout } from 'src/commands/auth';
import { serverInfo } from 'src/commands/server-info';
import { upload } from 'src/commands/asset.js';
import { login, logout } from 'src/commands/auth.js';
import { serverInfo } from 'src/commands/server-info.js';
import { version } from '../package.json';
const defaultConfigDirectory = path.join(os.homedir(), '.config/immich/');
+1 -1
View File
@@ -1,6 +1,6 @@
import mockfs from 'mock-fs';
import { readFileSync } from 'node:fs';
import { Batcher, CrawlOptions, crawl } from 'src/utils';
import { Batcher, CrawlOptions, crawl } from 'src/utils.js';
import { Mock } from 'vitest';
interface Test {
+3 -3
View File
@@ -8,10 +8,10 @@ import {
RELEASE_TYPES,
ReleaseError,
ReleaseInputError,
ReleaseOptions,
ReleaseType,
type ReleaseOptions,
type ReleaseType,
TextFile,
} from 'src/types';
} from 'src/types.js';
const root = join(dirname(fileURLToPath(import.meta.url)), '../../../');
+613 -918
View File
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -3,7 +3,9 @@ run = "pnpm install --filter immich --frozen-lockfile"
[tasks.build]
env._.path = "./node_modules/.bin"
run = "nest build"
# TODO we shouldn't technically need tsc-alias, but the nestjs tsconfig paths resolution is broken right now with ESM
# remove when https://github.com/nestjs/nest-cli/pull/3545 has been released
run = "nest build && tsc-alias"
[tasks.test]
env._.path = "./node_modules/.bin"
@@ -47,10 +49,7 @@ description = "Run database migration commands (create, generate, run, sync-orde
run = { task = "migrations query 'DROP schema public cascade; CREATE schema public;'" }
[tasks."schema-reset"]
run = [
{ task = ":schema-drop" },
{ task = "migrations run" },
]
run = [{ task = ":schema-drop" }, { task = "migrations run" }]
[tasks."email-dev"]
env._.path = "./node_modules/.bin"
@@ -78,5 +77,7 @@ run = [
run = [
{ task = ":ci-unit" },
{ task = ":ci-medium" },
{ task = ":migrations", args = ["verify-order"] },
{ task = ":migrations", args = [
"verify-order",
] },
]
-1
View File
@@ -4,7 +4,6 @@
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": false,
"webpack": false,
"plugins": [
{
"name": "@nestjs/swagger",
+18 -17
View File
@@ -5,13 +5,14 @@
"author": "",
"private": true,
"license": "GNU Affero General Public License version 3",
"type": "module",
"files": [
"bin",
"dist",
"helmet.json"
],
"scripts": {
"build": "nest build",
"build": "nest build && tsc-alias",
"format": "prettier --cache --check .",
"format:fix": "prettier --cache --write --list-different .",
"start": "pnpm run start:dev",
@@ -41,14 +42,14 @@
"@extism/extism": "2.0.0-rc13",
"@immich/plugin-sdk": "workspace:*",
"@immich/sql-tools": "^0.6.3",
"@nestjs/bullmq": "^11.0.1",
"@nestjs/common": "^11.0.4",
"@nestjs/core": "^11.0.4",
"@nestjs/platform-express": "^11.0.4",
"@nestjs/platform-socket.io": "^11.0.4",
"@nestjs/schedule": "^6.0.0",
"@nestjs/swagger": "^11.4.2",
"@nestjs/websockets": "^11.0.4",
"@nestjs/bullmq": "^12.0.0",
"@nestjs/common": "^12.0.0",
"@nestjs/core": "^12.0.0",
"@nestjs/platform-express": "^12.0.0",
"@nestjs/platform-socket.io": "^12.0.0",
"@nestjs/schedule": "^12.0.1",
"@nestjs/swagger": "^12.0.0",
"@nestjs/websockets": "^12.0.0",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-async-hooks": "^2.0.0",
"@opentelemetry/exporter-prometheus": "^0.222.0",
@@ -86,9 +87,9 @@
"jose": "^6.0.0",
"js-yaml": "^5.0.0",
"jsonwebtoken": "^9.0.2",
"kysely": "0.28.17",
"kysely": "^0.29.5",
"kysely-postgres-js": "^3.0.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"luxon": "^3.4.2",
"mnemonist": "^0.40.3",
"multer": "^2.0.2",
@@ -122,9 +123,9 @@
},
"devDependencies": {
"@eslint/js": "^10.0.0",
"@nestjs/cli": "^11.0.2",
"@nestjs/schematics": "^11.0.0",
"@nestjs/testing": "^11.0.4",
"@nestjs/cli": "^12.0.0",
"@nestjs/schematics": "^12.0.0",
"@nestjs/testing": "^12.0.0",
"@swc/core": "^1.4.14",
"@types/archiver": "^7.0.0",
"@types/async-lock": "^1.4.2",
@@ -136,7 +137,7 @@
"@types/fluent-ffmpeg": "^2.1.21",
"@types/js-yaml": "^4.0.9",
"@types/jsonwebtoken": "^9.0.10",
"@types/lodash": "^4.14.197",
"@types/lodash-es": "^4.14.197",
"@types/luxon": "^3.6.2",
"@types/mock-fs": "^4.13.1",
"@types/multer": "^2.0.0",
@@ -164,11 +165,11 @@
"supertest": "^7.1.0",
"tailwindcss": "^3.4.0",
"testcontainers": "^12.0.0",
"tsc-alias": "^1.8.16",
"typescript": "npm:@typescript/typescript6@^6.0.2",
"typescript-eslint": "^8.28.0",
"unplugin-swc": "^1.4.5",
"vite-tsconfig-paths": "^6.0.0",
"vitest": "^3.0.0"
"vitest": "^4.0.0"
},
"overrides": {
"sharp": "^0.35.3"
+8 -8
View File
@@ -5,14 +5,14 @@ import cookieParser from 'cookie-parser';
import helmetMiddleware from 'helmet';
import { existsSync } from 'node:fs';
import sirv from 'sirv';
import { IMMICH_SERVER_START, excludePaths, serverVersion } from 'src/constants';
import { MaintenanceWorkerService } from 'src/maintenance/maintenance-worker.service';
import { WebSocketAdapter } from 'src/middleware/websocket.adapter';
import { ConfigRepository } from 'src/repositories/config.repository';
import { LoggingRepository } from 'src/repositories/logging.repository';
import { bootstrapTelemetry } from 'src/repositories/telemetry.repository';
import { ApiService } from 'src/services/api.service';
import { useSwagger } from 'src/utils/misc';
import { IMMICH_SERVER_START, excludePaths, serverVersion } from 'src/constants.js';
import { MaintenanceWorkerService } from 'src/maintenance/maintenance-worker.service.js';
import { WebSocketAdapter } from 'src/middleware/websocket.adapter.js';
import { ConfigRepository } from 'src/repositories/config.repository.js';
import { LoggingRepository } from 'src/repositories/logging.repository.js';
import { bootstrapTelemetry } from 'src/repositories/telemetry.repository.js';
import { ApiService } from 'src/services/api.service.js';
import { useSwagger } from 'src/utils/misc.js';
export function configureTelemetry() {
const { telemetry } = new ConfigRepository().getEnv();
+33 -33
View File
@@ -6,39 +6,39 @@ import { ClsModule } from 'nestjs-cls';
import { KyselyModule } from 'nestjs-kysely';
import { OpenTelemetryModule } from 'nestjs-otel';
import { ZodSerializerInterceptor, ZodValidationPipe } from 'nestjs-zod';
import { commandsAndQuestions } from 'src/commands';
import { IWorker } from 'src/constants';
import { controllers } from 'src/controllers';
import { ImmichWorker } from 'src/enum';
import { MaintenanceAuthGuard } from 'src/maintenance/maintenance-auth.guard';
import { MaintenanceHealthRepository } from 'src/maintenance/maintenance-health.repository';
import { MaintenanceWebsocketRepository } from 'src/maintenance/maintenance-websocket.repository';
import { MaintenanceWorkerController } from 'src/maintenance/maintenance-worker.controller';
import { MaintenanceWorkerService } from 'src/maintenance/maintenance-worker.service';
import { AuthGuard } from 'src/middleware/auth.guard';
import { ErrorInterceptor } from 'src/middleware/error.interceptor';
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor';
import { GlobalExceptionFilter } from 'src/middleware/global-exception.filter';
import { LoggingInterceptor } from 'src/middleware/logging.interceptor';
import { repositories } from 'src/repositories';
import { AppRepository } from 'src/repositories/app.repository';
import { ConfigRepository } from 'src/repositories/config.repository';
import { DatabaseRepository } from 'src/repositories/database.repository';
import { EventRepository } from 'src/repositories/event.repository';
import { LoggingRepository } from 'src/repositories/logging.repository';
import { ProcessRepository } from 'src/repositories/process.repository';
import { StorageRepository } from 'src/repositories/storage.repository';
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
import { teardownTelemetry, TelemetryRepository } from 'src/repositories/telemetry.repository';
import { UserRepository } from 'src/repositories/user.repository';
import { WebsocketRepository } from 'src/repositories/websocket.repository';
import { services } from 'src/services';
import { AuthService } from 'src/services/auth.service';
import { CliService } from 'src/services/cli.service';
import { DatabaseBackupService } from 'src/services/database-backup.service';
import { QueueService } from 'src/services/queue.service';
import { getKyselyConfig } from 'src/utils/database';
import { configureUserAgent } from 'src/utils/fetch';
import { commandsAndQuestions } from 'src/commands/index.js';
import { IWorker } from 'src/constants.js';
import { controllers } from 'src/controllers/index.js';
import { ImmichWorker } from 'src/enum.js';
import { MaintenanceAuthGuard } from 'src/maintenance/maintenance-auth.guard.js';
import { MaintenanceHealthRepository } from 'src/maintenance/maintenance-health.repository.js';
import { MaintenanceWebsocketRepository } from 'src/maintenance/maintenance-websocket.repository.js';
import { MaintenanceWorkerController } from 'src/maintenance/maintenance-worker.controller.js';
import { MaintenanceWorkerService } from 'src/maintenance/maintenance-worker.service.js';
import { AuthGuard } from 'src/middleware/auth.guard.js';
import { ErrorInterceptor } from 'src/middleware/error.interceptor.js';
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor.js';
import { GlobalExceptionFilter } from 'src/middleware/global-exception.filter.js';
import { LoggingInterceptor } from 'src/middleware/logging.interceptor.js';
import { AppRepository } from 'src/repositories/app.repository.js';
import { ConfigRepository } from 'src/repositories/config.repository.js';
import { DatabaseRepository } from 'src/repositories/database.repository.js';
import { EventRepository } from 'src/repositories/event.repository.js';
import { repositories } from 'src/repositories/index.js';
import { LoggingRepository } from 'src/repositories/logging.repository.js';
import { ProcessRepository } from 'src/repositories/process.repository.js';
import { StorageRepository } from 'src/repositories/storage.repository.js';
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository.js';
import { teardownTelemetry, TelemetryRepository } from 'src/repositories/telemetry.repository.js';
import { UserRepository } from 'src/repositories/user.repository.js';
import { WebsocketRepository } from 'src/repositories/websocket.repository.js';
import { AuthService } from 'src/services/auth.service.js';
import { CliService } from 'src/services/cli.service.js';
import { DatabaseBackupService } from 'src/services/database-backup.service.js';
import { services } from 'src/services/index.js';
import { QueueService } from 'src/services/queue.service.js';
import { getKyselyConfig } from 'src/utils/database.js';
import { configureUserAgent } from 'src/utils/fetch.js';
const common = [...repositories, ...services, GlobalExceptionFilter];
+2 -2
View File
@@ -2,8 +2,8 @@
process.env.DB_URL = 'postgres://postgres:postgres@localhost:5432/immich';
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { ApiModule } from 'src/app.module';
import { useSwagger } from 'src/utils/misc';
import { ApiModule } from 'src/app.module.js';
import { useSwagger } from 'src/utils/misc.js';
const sync = async () => {
const app = await NestFactory.create<NestExpressApplication>(ApiModule, { preview: true });
+9 -9
View File
@@ -9,15 +9,15 @@ import { OpenTelemetryModule } from 'nestjs-otel';
import { mkdir, rm, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { format } from 'sql-formatter';
import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators';
import { repositories } from 'src/repositories';
import { AccessRepository } from 'src/repositories/access.repository';
import { ConfigRepository } from 'src/repositories/config.repository';
import { LoggingRepository } from 'src/repositories/logging.repository';
import { MachineLearningRepository } from 'src/repositories/machine-learning.repository';
import { SyncRepository } from 'src/repositories/sync.repository';
import { AuthService } from 'src/services/auth.service';
import { getKyselyConfig } from 'src/utils/database';
import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators.js';
import { AccessRepository } from 'src/repositories/access.repository.js';
import { ConfigRepository } from 'src/repositories/config.repository.js';
import { repositories } from 'src/repositories/index.js';
import { LoggingRepository } from 'src/repositories/logging.repository.js';
import { MachineLearningRepository } from 'src/repositories/machine-learning.repository.js';
import { SyncRepository } from 'src/repositories/sync.repository.js';
import { AuthService } from 'src/services/auth.service.js';
import { getKyselyConfig } from 'src/utils/database.js';
const handleError = (label: string, error: Error | any) => {
console.error(`${label} error: ${error}`);
+1 -1
View File
@@ -1,5 +1,5 @@
import { Command, CommandRunner, InquirerService, Question, QuestionSet } from 'nest-commander';
import { CliService } from 'src/services/cli.service';
import { CliService } from 'src/services/cli.service.js';
const prompt = (inquirer: InquirerService) => {
return function ask(): Promise<string> {
+9 -9
View File
@@ -1,16 +1,16 @@
import { GrantAdminCommand, PromptEmailQuestion, RevokeAdminCommand } from 'src/commands/grant-admin';
import { ListUsersCommand } from 'src/commands/list-users.command';
import { DisableMaintenanceModeCommand, EnableMaintenanceModeCommand } from 'src/commands/maintenance-mode';
import { GrantAdminCommand, PromptEmailQuestion, RevokeAdminCommand } from 'src/commands/grant-admin.js';
import { ListUsersCommand } from 'src/commands/list-users.command.js';
import { DisableMaintenanceModeCommand, EnableMaintenanceModeCommand } from 'src/commands/maintenance-mode.js';
import {
ChangeMediaLocationCommand,
PromptConfirmMoveQuestions,
PromptMediaLocationQuestions,
} from 'src/commands/media-location.command';
import { DisableOAuthLogin, EnableOAuthLogin } from 'src/commands/oauth-login';
import { DisablePasswordLoginCommand, EnablePasswordLoginCommand } from 'src/commands/password-login';
import { PromptPasswordResetQuestions, ResetAdminPasswordCommand } from 'src/commands/reset-admin-password.command';
import { SchemaCheck } from 'src/commands/schema-check';
import { VersionCommand } from 'src/commands/version.command';
} from 'src/commands/media-location.command.js';
import { DisableOAuthLogin, EnableOAuthLogin } from 'src/commands/oauth-login.js';
import { DisablePasswordLoginCommand, EnablePasswordLoginCommand } from 'src/commands/password-login.js';
import { PromptPasswordResetQuestions, ResetAdminPasswordCommand } from 'src/commands/reset-admin-password.command.js';
import { SchemaCheck } from 'src/commands/schema-check.js';
import { VersionCommand } from 'src/commands/version.command.js';
export const commandsAndQuestions = [
ResetAdminPasswordCommand,
+1 -1
View File
@@ -1,5 +1,5 @@
import { Command, CommandRunner } from 'nest-commander';
import { CliService } from 'src/services/cli.service';
import { CliService } from 'src/services/cli.service.js';
@Command({
name: 'list-users',
+1 -1
View File
@@ -1,5 +1,5 @@
import { Command, CommandRunner } from 'nest-commander';
import { CliService } from 'src/services/cli.service';
import { CliService } from 'src/services/cli.service.js';
@Command({
name: 'enable-maintenance-mode',
@@ -1,5 +1,5 @@
import { Command, CommandRunner, InquirerService, Question, QuestionSet } from 'nest-commander';
import { CliService } from 'src/services/cli.service';
import { CliService } from 'src/services/cli.service.js';
@Command({
name: 'change-media-location',
+1 -1
View File
@@ -1,5 +1,5 @@
import { Command, CommandRunner } from 'nest-commander';
import { CliService } from 'src/services/cli.service';
import { CliService } from 'src/services/cli.service.js';
@Command({
name: 'enable-oauth-login',
+1 -1
View File
@@ -1,5 +1,5 @@
import { Command, CommandRunner } from 'nest-commander';
import { CliService } from 'src/services/cli.service';
import { CliService } from 'src/services/cli.service.js';
@Command({
name: 'enable-password-login',
@@ -1,6 +1,6 @@
import { Command, CommandRunner, InquirerService, Question, QuestionSet } from 'nest-commander';
import { UserAdminResponseDto } from 'src/dtos/user.dto';
import { CliService } from 'src/services/cli.service';
import { UserAdminResponseDto } from 'src/dtos/user.dto.js';
import { CliService } from 'src/services/cli.service.js';
const prompt = (inquirer: InquirerService) => {
return (admin: UserAdminResponseDto) => {
+2 -2
View File
@@ -1,7 +1,7 @@
import { asHuman } from '@immich/sql-tools';
import { Command, CommandRunner } from 'nest-commander';
import { ErrorMessages } from 'src/constants';
import { CliService } from 'src/services/cli.service';
import { ErrorMessages } from 'src/constants.js';
import { CliService } from 'src/services/cli.service.js';
@Command({
name: 'schema-check',
+1 -1
View File
@@ -1,5 +1,5 @@
import { Command, CommandRunner } from 'nest-commander';
import { VersionService } from 'src/services/version.service';
import { VersionService } from 'src/services/version.service.js';
@Command({
name: 'version',
+2 -3
View File
@@ -9,7 +9,7 @@ import {
TranscodeHardwareAcceleration,
VectorIndex,
VideoCodec,
} from 'src/enum';
} from 'src/enum.js';
export const IMMICH_SERVER_START = 'Immich Server is listening';
@@ -49,8 +49,7 @@ export const LOGIN_DUMMY_HASH = '$2b$10$abcdefghijklmnopqrstuuABCDEFGHIJKLMNOPQR
export const IWorker = 'IWorker';
// eslint-disable-next-line unicorn/prefer-module
const basePath = dirname(__filename);
const basePath = dirname(import.meta.filename);
const packageFile = join(basePath, '..', 'package.json');
const { version } = JSON.parse(readFileSync(packageFile, 'utf8'));
export const serverVersion = new SemVer(version);
@@ -1,8 +1,8 @@
import { ActivityController } from 'src/controllers/activity.controller';
import { ActivityService } from 'src/services/activity.service';
import { ActivityController } from 'src/controllers/activity.controller.js';
import { ActivityService } from 'src/services/activity.service.js';
import request from 'supertest';
import { factory } from 'test/small.factory';
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils';
import { factory } from 'test/small.factory.js';
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils.js';
describe(ActivityController.name, () => {
let ctx: ControllerContext;
@@ -1,19 +1,19 @@
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Query, Res } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Response } from 'express';
import { Endpoint, HistoryBuilder } from 'src/decorators';
import type { Response } from 'express';
import { Endpoint, HistoryBuilder } from 'src/decorators.js';
import {
ActivityCreateDto,
ActivityDto,
ActivityResponseDto,
ActivitySearchDto,
ActivityStatisticsResponseDto,
} from 'src/dtos/activity.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { ApiTag, Permission } from 'src/enum';
import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { ActivityService } from 'src/services/activity.service';
import { UUIDParamDto } from 'src/validation';
} from 'src/dtos/activity.dto.js';
import type { AuthDto } from 'src/dtos/auth.dto.js';
import { ApiTag, Permission } from 'src/enum.js';
import { Auth, Authenticated } from 'src/middleware/auth.guard.js';
import { ActivityService } from 'src/services/activity.service.js';
import { UUIDParamDto } from 'src/validation.js';
@ApiTags(ApiTag.Activities)
@Controller('activities')
@@ -1,8 +1,8 @@
import { AlbumController } from 'src/controllers/album.controller';
import { AlbumService } from 'src/services/album.service';
import { AlbumController } from 'src/controllers/album.controller.js';
import { AlbumService } from 'src/services/album.service.js';
import request from 'supertest';
import { factory } from 'test/small.factory';
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils';
import { factory } from 'test/small.factory.js';
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils.js';
describe(AlbumController.name, () => {
let ctx: ControllerContext;
+9 -9
View File
@@ -1,6 +1,6 @@
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post, Put, Query } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Endpoint, HistoryBuilder } from 'src/decorators';
import { Endpoint, HistoryBuilder } from 'src/decorators.js';
import {
AddUsersDto,
AlbumResponseDto,
@@ -12,14 +12,14 @@ import {
GetAlbumsDto,
UpdateAlbumDto,
UpdateAlbumUserDto,
} from 'src/dtos/album.dto';
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { MapMarkerResponseDto } from 'src/dtos/map.dto';
import { ApiTag, Permission } from 'src/enum';
import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { AlbumService } from 'src/services/album.service';
import { UUIDParamDto } from 'src/validation';
} from 'src/dtos/album.dto.js';
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto.js';
import type { AuthDto } from 'src/dtos/auth.dto.js';
import { MapMarkerResponseDto } from 'src/dtos/map.dto.js';
import { ApiTag, Permission } from 'src/enum.js';
import { Auth, Authenticated } from 'src/middleware/auth.guard.js';
import { AlbumService } from 'src/services/album.service.js';
import { UUIDParamDto } from 'src/validation.js';
@ApiTags(ApiTag.Albums)
@Controller('albums')
@@ -1,9 +1,9 @@
import { ApiKeyController } from 'src/controllers/api-key.controller';
import { Permission } from 'src/enum';
import { ApiKeyService } from 'src/services/api-key.service';
import { ApiKeyController } from 'src/controllers/api-key.controller.js';
import { Permission } from 'src/enum.js';
import { ApiKeyService } from 'src/services/api-key.service.js';
import request from 'supertest';
import { factory } from 'test/small.factory';
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils';
import { factory } from 'test/small.factory.js';
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils.js';
describe(ApiKeyController.name, () => {
let ctx: ControllerContext;
+7 -7
View File
@@ -1,12 +1,12 @@
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post, Put } from '@nestjs/common';
import { ApiExcludeEndpoint, ApiTags } from '@nestjs/swagger';
import { Endpoint, HistoryBuilder } from 'src/decorators';
import { ApiKeyCreateDto, ApiKeyCreateResponseDto, ApiKeyResponseDto, ApiKeyUpdateDto } from 'src/dtos/api-key.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { ApiTag, Permission } from 'src/enum';
import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { ApiKeyService } from 'src/services/api-key.service';
import { UUIDParamDto } from 'src/validation';
import { Endpoint, HistoryBuilder } from 'src/decorators.js';
import { ApiKeyCreateDto, ApiKeyCreateResponseDto, ApiKeyResponseDto, ApiKeyUpdateDto } from 'src/dtos/api-key.dto.js';
import type { AuthDto } from 'src/dtos/auth.dto.js';
import { ApiTag, Permission } from 'src/enum.js';
import { Auth, Authenticated } from 'src/middleware/auth.guard.js';
import { ApiKeyService } from 'src/services/api-key.service.js';
import { UUIDParamDto } from 'src/validation.js';
@ApiTags(ApiTag.ApiKeys)
@Controller('api-keys')
@@ -1,7 +1,7 @@
import { AppController } from 'src/controllers/app.controller';
import { SystemConfigService } from 'src/services/system-config.service';
import { AppController } from 'src/controllers/app.controller.js';
import { SystemConfigService } from 'src/services/system-config.service.js';
import request from 'supertest';
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils';
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils.js';
describe(AppController.name, () => {
let ctx: ControllerContext;
+2 -2
View File
@@ -1,7 +1,7 @@
import { Controller, Get, Header } from '@nestjs/common';
import { ApiExcludeEndpoint } from '@nestjs/swagger';
import { Authenticated } from 'src/middleware/auth.guard';
import { SystemConfigService } from 'src/services/system-config.service';
import { Authenticated } from 'src/middleware/auth.guard.js';
import { SystemConfigService } from 'src/services/system-config.service.js';
@Controller()
export class AppController {
+10 -10
View File
@@ -1,15 +1,15 @@
import { Controller, Delete, Get, HttpCode, HttpStatus, Next, Param, Query, Res } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { NextFunction, Response } from 'express';
import { Endpoint, HistoryBuilder } from 'src/decorators';
import { AssetFileResponseDto, AssetFileSearchDto } from 'src/dtos/asset-file.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { ApiTag, Permission } from 'src/enum';
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
import { LoggingRepository } from 'src/repositories/logging.repository';
import { AssetFileService } from 'src/services/asset-file.service';
import { sendFile } from 'src/utils/file';
import { UUIDParamDto } from 'src/validation';
import type { NextFunction, Response } from 'express';
import { Endpoint, HistoryBuilder } from 'src/decorators.js';
import { AssetFileResponseDto, AssetFileSearchDto } from 'src/dtos/asset-file.dto.js';
import type { AuthDto } from 'src/dtos/auth.dto.js';
import { ApiTag, Permission } from 'src/enum.js';
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard.js';
import { LoggingRepository } from 'src/repositories/logging.repository.js';
import { AssetFileService } from 'src/services/asset-file.service.js';
import { sendFile } from 'src/utils/file.js';
import { UUIDParamDto } from 'src/validation.js';
@ApiTags(ApiTag.AssetFiles)
@Controller('asset-files')
@@ -1,11 +1,11 @@
import { AssetMediaController } from 'src/controllers/asset-media.controller';
import { AssetMediaStatus } from 'src/dtos/asset-media-response.dto';
import { AssetMetadataKey } from 'src/enum';
import { LoggingRepository } from 'src/repositories/logging.repository';
import { AssetMediaService } from 'src/services/asset-media.service';
import { AssetMediaController } from 'src/controllers/asset-media.controller.js';
import { AssetMediaStatus } from 'src/dtos/asset-media-response.dto.js';
import { AssetMetadataKey } from 'src/enum.js';
import { LoggingRepository } from 'src/repositories/logging.repository.js';
import { AssetMediaService } from 'src/services/asset-media.service.js';
import request from 'supertest';
import { factory } from 'test/small.factory';
import { automock, ControllerContext, controllerSetup, mockBaseService } from 'test/utils';
import { factory } from 'test/small.factory.js';
import { automock, ControllerContext, controllerSetup, mockBaseService } from 'test/utils.js';
const makeUploadDto = (options?: { omit: string }): Record<string, any> => {
const dto: Record<string, any> = {
@@ -15,30 +15,30 @@ import {
UseInterceptors,
} from '@nestjs/common';
import { ApiBody, ApiConsumes, ApiHeader, ApiResponse, ApiTags } from '@nestjs/swagger';
import { NextFunction, Request, Response } from 'express';
import { Endpoint, HistoryBuilder } from 'src/decorators';
import { type NextFunction, type Request, type Response } from 'express';
import { Endpoint, HistoryBuilder } from 'src/decorators.js';
import {
AssetBulkUploadCheckResponseDto,
AssetMediaResponseDto,
AssetMediaStatus,
} from 'src/dtos/asset-media-response.dto';
} from 'src/dtos/asset-media-response.dto.js';
import {
AssetBulkUploadCheckDto,
AssetMediaCreateDto,
AssetMediaOptionsDto,
AssetMediaSize,
} from 'src/dtos/asset-media.dto';
import { AssetDownloadOriginalDto } from 'src/dtos/asset.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { ApiTag, ImmichHeader, Permission, RouteKey } from 'src/enum';
import { AssetUploadInterceptor } from 'src/middleware/asset-upload.interceptor';
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
import { FileUploadInterceptor, getFiles } from 'src/middleware/file-upload.interceptor';
import { LoggingRepository } from 'src/repositories/logging.repository';
import { AssetMediaService } from 'src/services/asset-media.service';
import { UploadFiles } from 'src/types';
import { ImmichFileResponse, sendFile } from 'src/utils/file';
import { FileNotEmptyValidator, UUIDParamDto } from 'src/validation';
} from 'src/dtos/asset-media.dto.js';
import { AssetDownloadOriginalDto } from 'src/dtos/asset.dto.js';
import { type AuthDto } from 'src/dtos/auth.dto.js';
import { ApiTag, ImmichHeader, Permission, RouteKey } from 'src/enum.js';
import { AssetUploadInterceptor } from 'src/middleware/asset-upload.interceptor.js';
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard.js';
import { FileUploadInterceptor, getFiles } from 'src/middleware/file-upload.interceptor.js';
import { LoggingRepository } from 'src/repositories/logging.repository.js';
import { AssetMediaService } from 'src/services/asset-media.service.js';
import type { UploadFiles } from 'src/types.js';
import { ImmichFileResponse, sendFile } from 'src/utils/file.js';
import { FileNotEmptyValidator, UUIDParamDto } from 'src/validation.js';
@ApiTags(ApiTag.Assets)
@Controller(RouteKey.Asset)
@@ -1,9 +1,9 @@
import { AssetController } from 'src/controllers/asset.controller';
import { AssetMetadataKey } from 'src/enum';
import { AssetService } from 'src/services/asset.service';
import { AssetController } from 'src/controllers/asset.controller.js';
import { AssetMetadataKey } from 'src/enum.js';
import { AssetService } from 'src/services/asset.service.js';
import request from 'supertest';
import { factory } from 'test/small.factory';
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils';
import { factory } from 'test/small.factory.js';
import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils.js';
describe(AssetController.name, () => {
let ctx: ControllerContext;
+10 -10
View File
@@ -1,7 +1,7 @@
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post, Put, Query } from '@nestjs/common';
import { ApiExcludeEndpoint, ApiTags } from '@nestjs/swagger';
import { Endpoint, HistoryBuilder } from 'src/decorators';
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
import { Endpoint, HistoryBuilder } from 'src/decorators.js';
import { AssetResponseDto } from 'src/dtos/asset-response.dto.js';
import {
AssetBulkDeleteDto,
AssetBulkUpdateDto,
@@ -16,14 +16,14 @@ import {
AssetStatsDto,
AssetStatsResponseDto,
UpdateAssetDto,
} from 'src/dtos/asset.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { AssetEditsCreateDto, AssetEditsResponseDto } from 'src/dtos/editing.dto';
import { AssetOcrResponseDto } from 'src/dtos/ocr.dto';
import { ApiTag, Permission, RouteKey } from 'src/enum';
import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { AssetService } from 'src/services/asset.service';
import { UUIDParamDto } from 'src/validation';
} from 'src/dtos/asset.dto.js';
import type { AuthDto } from 'src/dtos/auth.dto.js';
import { AssetEditsCreateDto, AssetEditsResponseDto } from 'src/dtos/editing.dto.js';
import { AssetOcrResponseDto } from 'src/dtos/ocr.dto.js';
import { ApiTag, Permission, RouteKey } from 'src/enum.js';
import { Auth, Authenticated } from 'src/middleware/auth.guard.js';
import { AssetService } from 'src/services/asset.service.js';
import { UUIDParamDto } from 'src/validation.js';
@ApiTags(ApiTag.Assets)
@Controller(RouteKey.Asset)

Some files were not shown because too many files have changed in this diff Show More