diff --git a/open-api/bin/generate-open-api.sh b/open-api/bin/generate-open-api.sh index 76012383cf..f0a211abe4 100755 --- a/open-api/bin/generate-open-api.sh +++ b/open-api/bin/generate-open-api.sh @@ -19,7 +19,7 @@ function dart { function typescript { rm -rf ./typescript-sdk/client npx --yes @openapitools/openapi-generator-cli generate -g typescript-axios -i ./immich-openapi-specs.json -o ./typescript-sdk/axios-client --additional-properties=useSingleRequestParameter=true,supportsES6=true - npx --yes oazapfts --optimistic --argumentStyle=object immich-openapi-specs.json typescript-sdk/fetch-client.ts + npx --yes oazapfts --optimistic --argumentStyle=object --useEnumType immich-openapi-specs.json typescript-sdk/fetch-client.ts npm --prefix typescript-sdk ci && npm --prefix typescript-sdk run build } diff --git a/open-api/typescript-sdk/fetch-client.ts b/open-api/typescript-sdk/fetch-client.ts index 00b8c68326..e37b43ca79 100644 --- a/open-api/typescript-sdk/fetch-client.ts +++ b/open-api/typescript-sdk/fetch-client.ts @@ -14,9 +14,6 @@ const oazapfts = Oazapfts.runtime(defaults); export const servers = { server1: "/api" }; -export type ReactionLevel = "album" | "asset"; -export type ReactionType = "comment" | "like"; -export type UserAvatarColor = "primary" | "pink" | "red" | "yellow" | "blue" | "green" | "purple" | "orange" | "gray" | "amber"; export type UserDto = { avatarColor: UserAvatarColor; email: string; @@ -29,7 +26,7 @@ export type ActivityResponseDto = { comment?: string | null; createdAt: string; id: string; - "type": "comment" | "like"; + "type": Type; user: UserDto; }; export type ActivityCreateDto = { @@ -103,14 +100,12 @@ export type SmartInfoResponseDto = { objects?: string[] | null; tags?: string[] | null; }; -export type TagTypeEnum = "OBJECT" | "FACE" | "CUSTOM"; export type TagResponseDto = { id: string; name: string; "type": TagTypeEnum; userId: string; }; -export type AssetTypeEnum = "IMAGE" | "VIDEO" | "AUDIO" | "OTHER"; export type AssetResponseDto = { /** base64 encoded sha1 hash */ checksum: string; @@ -186,7 +181,7 @@ export type BulkIdsDto = { ids: string[]; }; export type BulkIdResponseDto = { - error?: "duplicate" | "no_permission" | "not_found" | "unknown"; + error?: Error; id: string; success: boolean; }; @@ -232,10 +227,10 @@ export type AssetBulkUploadCheckDto = { assets: AssetBulkUploadCheckItem[]; }; export type AssetBulkUploadCheckResult = { - action: "accept" | "reject"; + action: Action; assetId?: string; id: string; - reason?: "duplicate" | "unsupported-format"; + reason?: Reason; }; export type AssetBulkUploadCheckResponseDto = { results: AssetBulkUploadCheckResult[]; @@ -261,7 +256,6 @@ export type CheckExistingAssetsDto = { export type CheckExistingAssetsResponseDto = { existingIds: string[]; }; -export type AssetJobName = "regenerate-thumbnail" | "refresh-metadata" | "transcode-video"; export type AssetJobsDto = { assetIds: string[]; name: AssetJobName; @@ -284,8 +278,6 @@ export type AssetStatsResponseDto = { total: number; videos: number; }; -export type ThumbnailFormat = "JPEG" | "WEBP"; -export type TimeBucketSize = "DAY" | "MONTH"; export type TimeBucketResponseDto = { count: number; timeBucket: string; @@ -319,14 +311,10 @@ export type UpdateAssetDto = { latitude?: number; longitude?: number; }; -export type AssetOrder = "asc" | "desc"; -export type EntityType = "ASSET" | "ALBUM"; export type AuditDeletesResponseDto = { ids: string[]; needsFullSync: boolean; }; -export type PathEntityType = "asset" | "person" | "user"; -export type PathType = "original" | "jpeg_thumbnail" | "webp_thumbnail" | "encoded_video" | "sidecar" | "face" | "profile"; export type FileReportItemDto = { checksum?: string; entityId: string; @@ -452,13 +440,10 @@ export type AllJobStatusResponseDto = { thumbnailGeneration: JobStatusDto; videoConversion: JobStatusDto; }; -export type JobName = "thumbnailGeneration" | "metadataExtraction" | "videoConversion" | "faceDetection" | "facialRecognition" | "smartSearch" | "backgroundTask" | "storageTemplateMigration" | "migration" | "search" | "sidecar" | "library"; -export type JobCommand = "start" | "pause" | "resume" | "empty" | "clear-failed"; export type JobCommandDto = { command: JobCommand; force: boolean; }; -export type LibraryType = "UPLOAD" | "EXTERNAL"; export type LibraryResponseDto = { assetCount: number; createdAt: string; @@ -603,7 +588,6 @@ export type SearchExploreResponseDto = { fieldName: string; items: SearchExploreItem[]; }; -export type SearchSuggestionType = "country" | "state" | "city" | "camera-make" | "camera-model"; export type ServerInfoResponseDto = { diskAvailable: string; diskAvailableRaw: number; @@ -665,7 +649,6 @@ export type ServerVersionResponseDto = { minor: number; patch: number; }; -export type SharedLinkType = "ALBUM" | "INDIVIDUAL"; export type SharedLinkResponseDto = { album?: AlbumResponseDto; allowDownload: boolean; @@ -707,21 +690,15 @@ export type SharedLinkEditDto = { }; export type AssetIdsResponseDto = { assetId: string; - error?: "duplicate" | "no_permission" | "not_found"; + error?: Error2; success: boolean; }; -export type TranscodeHwAccel = "nvenc" | "qsv" | "vaapi" | "rkmpp" | "disabled"; -export type AudioCodec = "mp3" | "aac" | "libopus"; -export type VideoCodec = "h264" | "hevc" | "vp9"; -export type CqMode = "auto" | "cqp" | "icq"; -export type ToneMapping = "hable" | "mobius" | "reinhard" | "disabled"; -export type TranscodePolicy = "all" | "optimal" | "bitrate" | "required" | "disabled"; export type SystemConfigFFmpegDto = { - accel: TranscodeHwAccel; + accel: TranscodeHWAccel; acceptedAudioCodecs: AudioCodec[]; acceptedVideoCodecs: VideoCodec[]; bframes: number; - cqMode: CqMode; + cqMode: CQMode; crf: number; gopSize: number; maxBitrate: string; @@ -766,16 +743,13 @@ export type SystemConfigLibraryDto = { scan: SystemConfigLibraryScanDto; watch: SystemConfigLibraryWatchDto; }; -export type LogLevel = "verbose" | "debug" | "log" | "warn" | "error" | "fatal"; export type SystemConfigLoggingDto = { enabled: boolean; level: LogLevel; }; -export type ClipMode = "vision" | "text"; -export type ModelType = "facial-recognition" | "clip"; export type ClipConfig = { enabled: boolean; - mode?: ClipMode; + mode?: CLIPMode; modelName: string; modelType?: ModelType; }; @@ -833,7 +807,6 @@ export type SystemConfigStorageTemplateDto = { export type SystemConfigThemeDto = { customCss: string; }; -export type Colorspace = "srgb" | "p3"; export type SystemConfigThumbnailDto = { colorspace: Colorspace; jpegSize: number; @@ -861,7 +834,6 @@ export type SystemConfigDto = { thumbnail: SystemConfigThumbnailDto; trash: SystemConfigTrashDto; }; -export type MapTheme = "light" | "dark"; export type SystemConfigTemplateStorageOptionDto = { dayOptions: string[]; hourOptions: string[]; @@ -2716,3 +2688,187 @@ export function restoreUser({ id }: { method: "POST" })); } +export enum ReactionLevel { + Album = "album", + Asset = "asset" +} +export enum ReactionType { + Comment = "comment", + Like = "like" +} +export enum Type { + Comment = "comment", + Like = "like" +} +export enum UserAvatarColor { + Primary = "primary", + Pink = "pink", + Red = "red", + Yellow = "yellow", + Blue = "blue", + Green = "green", + Purple = "purple", + Orange = "orange", + Gray = "gray", + Amber = "amber" +} +export enum TagTypeEnum { + Object = "OBJECT", + Face = "FACE", + Custom = "CUSTOM" +} +export enum AssetTypeEnum { + Image = "IMAGE", + Video = "VIDEO", + Audio = "AUDIO", + Other = "OTHER" +} +export enum Error { + Duplicate = "duplicate", + NoPermission = "no_permission", + NotFound = "not_found", + Unknown = "unknown" +} +export enum Action { + Accept = "accept", + Reject = "reject" +} +export enum Reason { + Duplicate = "duplicate", + UnsupportedFormat = "unsupported-format" +} +export enum AssetJobName { + RegenerateThumbnail = "regenerate-thumbnail", + RefreshMetadata = "refresh-metadata", + TranscodeVideo = "transcode-video" +} +export enum ThumbnailFormat { + Jpeg = "JPEG", + Webp = "WEBP" +} +export enum TimeBucketSize { + Day = "DAY", + Month = "MONTH" +} +export enum AssetOrder { + Asc = "asc", + Desc = "desc" +} +export enum EntityType { + Asset = "ASSET", + Album = "ALBUM" +} +export enum PathEntityType { + Asset = "asset", + Person = "person", + User = "user" +} +export enum PathType { + Original = "original", + JpegThumbnail = "jpeg_thumbnail", + WebpThumbnail = "webp_thumbnail", + EncodedVideo = "encoded_video", + Sidecar = "sidecar", + Face = "face", + Profile = "profile" +} +export enum JobName { + ThumbnailGeneration = "thumbnailGeneration", + MetadataExtraction = "metadataExtraction", + VideoConversion = "videoConversion", + FaceDetection = "faceDetection", + FacialRecognition = "facialRecognition", + SmartSearch = "smartSearch", + BackgroundTask = "backgroundTask", + StorageTemplateMigration = "storageTemplateMigration", + Migration = "migration", + Search = "search", + Sidecar = "sidecar", + Library = "library" +} +export enum JobCommand { + Start = "start", + Pause = "pause", + Resume = "resume", + Empty = "empty", + ClearFailed = "clear-failed" +} +export enum LibraryType { + Upload = "UPLOAD", + External = "EXTERNAL" +} +export enum SearchSuggestionType { + Country = "country", + State = "state", + City = "city", + CameraMake = "camera-make", + CameraModel = "camera-model" +} +export enum SharedLinkType { + Album = "ALBUM", + Individual = "INDIVIDUAL" +} +export enum Error2 { + Duplicate = "duplicate", + NoPermission = "no_permission", + NotFound = "not_found" +} +export enum TranscodeHWAccel { + Nvenc = "nvenc", + Qsv = "qsv", + Vaapi = "vaapi", + Rkmpp = "rkmpp", + Disabled = "disabled" +} +export enum AudioCodec { + Mp3 = "mp3", + Aac = "aac", + Libopus = "libopus" +} +export enum VideoCodec { + H264 = "h264", + Hevc = "hevc", + Vp9 = "vp9" +} +export enum CQMode { + Auto = "auto", + Cqp = "cqp", + Icq = "icq" +} +export enum ToneMapping { + Hable = "hable", + Mobius = "mobius", + Reinhard = "reinhard", + Disabled = "disabled" +} +export enum TranscodePolicy { + All = "all", + Optimal = "optimal", + Bitrate = "bitrate", + Required = "required", + Disabled = "disabled" +} +export enum LogLevel { + Verbose = "verbose", + Debug = "debug", + Log = "log", + Warn = "warn", + Error = "error", + Fatal = "fatal" +} +export enum CLIPMode { + Vision = "vision", + Text = "text" +} +export enum ModelType { + FacialRecognition = "facial-recognition", + Clip = "clip" +} +export enum Colorspace { + Srgb = "srgb", + P3 = "p3" +} +export enum MapTheme { + Light = "light", + Dark = "dark" +} diff --git a/open-api/typescript-sdk/tsconfig.fetch.json b/open-api/typescript-sdk/tsconfig.fetch.json index 58ef1ffa6b..92d17ebda9 100644 --- a/open-api/typescript-sdk/tsconfig.fetch.json +++ b/open-api/typescript-sdk/tsconfig.fetch.json @@ -1,5 +1,5 @@ { - "include": ["fetch.ts"], + "include": ["fetch.ts", "fetch-client.ts"], "compilerOptions": { "target": "esnext", "strict": true, diff --git a/web/src/api/index.ts b/web/src/api/index.ts deleted file mode 100644 index 886f439d8e..0000000000 --- a/web/src/api/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './api'; -export * from '@immich/sdk/axios'; -export * from './utils'; diff --git a/web/src/api/types.ts b/web/src/api/types.ts deleted file mode 100644 index 7a2ae17f67..0000000000 --- a/web/src/api/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Configuration } from '@immich/sdk/axios'; - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export type ApiFp = (configuration: Configuration) => Record any>; - -export type OmitLast = T extends readonly [...infer U, any?] ? U : [...T]; - -export type ApiParams> = OmitLast[K]>>; diff --git a/web/src/api/utils.ts b/web/src/api/utils.ts deleted file mode 100644 index decfefc560..0000000000 --- a/web/src/api/utils.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { finishOAuth, linkOAuthAccount, startOAuth, unlinkOAuthAccount } from '@immich/sdk'; -import { type UserResponseDto } from '@immich/sdk/axios'; -import type { AxiosError } from 'axios'; -import { - NotificationType, - notificationController, -} from '../lib/components/shared-components/notification/notification'; -import { handleError } from '../lib/utils/handle-error'; - -export type ApiError = AxiosError<{ message: string }>; - -export const copyToClipboard = async (secret: string) => { - try { - await navigator.clipboard.writeText(secret); - notificationController.show({ message: 'Copied to clipboard!', type: NotificationType.Info }); - } catch (error) { - handleError(error, 'Cannot copy to clipboard, make sure you are accessing the page through https'); - } -}; - -export const makeSharedLinkUrl = (externalDomain: string, key: string) => { - let url = externalDomain || window.location.origin; - if (!url.endsWith('/')) { - url += '/'; - } - return `${url}share/${key}`; -}; - -export const oauth = { - isCallback: (location: Location) => { - const search = location.search; - return search.includes('code=') || search.includes('error='); - }, - isAutoLaunchDisabled: (location: Location) => { - const values = ['autoLaunch=0', 'password=1', 'password=true']; - for (const value of values) { - if (location.search.includes(value)) { - return true; - } - } - return false; - }, - authorize: async (location: Location) => { - try { - const redirectUri = location.href.split('?')[0]; - const { url } = await startOAuth({ oAuthConfigDto: { redirectUri } }); - window.location.href = url; - return true; - } catch (error) { - handleError(error, 'Unable to login with OAuth'); - return false; - } - }, - login: (location: Location) => { - return finishOAuth({ oAuthCallbackDto: { url: location.href } }); - }, - link: (location: Location): Promise => { - return linkOAuthAccount({ oAuthCallbackDto: { url: location.href } }); - }, - unlink: () => { - return unlinkOAuthAccount(); - }, -}; diff --git a/web/src/api/api.ts b/web/src/lib/api/index.ts similarity index 57% rename from web/src/api/api.ts rename to web/src/lib/api/index.ts index 53340cb455..de8a5f722f 100644 --- a/web/src/api/api.ts +++ b/web/src/lib/api/index.ts @@ -4,12 +4,10 @@ class ImmichApi { public downloadApi: DownloadApi; public assetApi: AssetApi; - private config: configuration.Configuration; - constructor(parameters: configuration.ConfigurationParameters) { - this.config = new configuration.Configuration(parameters); - this.downloadApi = new DownloadApi(this.config); - this.assetApi = new AssetApi(this.config); + const config = new configuration.Configuration(parameters); + this.downloadApi = new DownloadApi(config); + this.assetApi = new AssetApi(config); } } diff --git a/web/src/lib/components/admin-page/jobs/job-tile.svelte b/web/src/lib/components/admin-page/jobs/job-tile.svelte index 42f489d41d..9e47386692 100644 --- a/web/src/lib/components/admin-page/jobs/job-tile.svelte +++ b/web/src/lib/components/admin-page/jobs/job-tile.svelte @@ -3,8 +3,7 @@ import Button from '$lib/components/elements/buttons/button.svelte'; import Icon from '$lib/components/elements/icon.svelte'; import { locale } from '$lib/stores/preferences.store'; - import { type JobCommandDto, type JobCountsDto, type QueueStatusDto } from '@immich/sdk'; - import { JobCommand } from '@immich/sdk/axios'; + import { JobCommand, type JobCommandDto, type JobCountsDto, type QueueStatusDto } from '@immich/sdk'; import { mdiAlertCircle, mdiAllInclusive, diff --git a/web/src/lib/components/admin-page/jobs/jobs-panel.svelte b/web/src/lib/components/admin-page/jobs/jobs-panel.svelte index 7ab7c0462a..60756166f2 100644 --- a/web/src/lib/components/admin-page/jobs/jobs-panel.svelte +++ b/web/src/lib/components/admin-page/jobs/jobs-panel.svelte @@ -6,8 +6,7 @@ import { featureFlags } from '$lib/stores/server-config.store'; import { getJobName } from '$lib/utils'; import { handleError } from '$lib/utils/handle-error'; - import { sendJobCommand, type AllJobStatusResponseDto, type JobCommandDto } from '@immich/sdk'; - import { JobCommand, JobName } from '@immich/sdk/axios'; + import { JobCommand, JobName, sendJobCommand, type AllJobStatusResponseDto, type JobCommandDto } from '@immich/sdk'; import { mdiFaceRecognition, mdiFileJpgBox, diff --git a/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte b/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte index b0f5a9c088..cd73b77f44 100644 --- a/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte +++ b/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte @@ -1,7 +1,14 @@ diff --git a/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte b/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte index 85ea60545c..f29e6f9eaf 100644 --- a/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte +++ b/web/src/lib/components/admin-page/settings/logging-settings/logging-settings.svelte @@ -1,6 +1,5 @@