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

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