mirror of
https://github.com/immich-app/immich.git
synced 2026-07-28 14:47:30 -07:00
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/docker-in-docker:2": {
|
||||
"version": "2.17.0",
|
||||
"resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c",
|
||||
"integrity": "sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c"
|
||||
"ghcr.io/devcontainers/features/docker-in-docker:4": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:4fa87399214366e320d489991769c4f3f461e1ffe461f54eea78a41b34945bb5",
|
||||
"integrity": "sha256:4fa87399214366e320d489991769c4f3f461e1ffe461f54eea78a41b34945bb5"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^10.0.0",
|
||||
"@faker-js/faker": "^10.1.0",
|
||||
"@futo-org/backups-orchestrator-ui": "0.12.0",
|
||||
"@futo-org/backups-orchestrator-ui": "0.19.3",
|
||||
"@immich/cli": "workspace:*",
|
||||
"@immich/e2e-auth-server": "workspace:*",
|
||||
"@immich/sdk": "workspace:*",
|
||||
|
||||
@@ -1337,6 +1337,7 @@
|
||||
"main_branch_warning": "You're using a development version; we strongly recommend using a release version!",
|
||||
"main_menu": "Main menu",
|
||||
"maintenance_action_restore": "Restoring Database",
|
||||
"maintenance_action_rollback": "Restoring from Backup",
|
||||
"maintenance_description": "Immich has been put into <link>maintenance mode</link>.",
|
||||
"maintenance_end": "End maintenance mode",
|
||||
"maintenance_logged_in_as": "Currently logged in as {user}",
|
||||
|
||||
@@ -82,35 +82,6 @@ url_api = "https://api.github.com/repos/extism/js-pdk/releases/assets/353224133"
|
||||
version = "7.1.3-6"
|
||||
backend = "github:jellyfin/jellyfin-ffmpeg"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg".options]
|
||||
asset_pattern = "jellyfin-ffmpeg_*_portable_macarm64-gpl.tar.xz"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.macos-arm64"]
|
||||
checksum = "sha256:e024d5e78d5414e75f0181036cd21373fafb9270c72894dfd7dbda2572439820"
|
||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_macarm64-gpl.tar.xz"
|
||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/408995838"
|
||||
|
||||
[[tools."github:jellyfin/jellyfin-ffmpeg"]]
|
||||
version = "7.1.3-6"
|
||||
backend = "github:jellyfin/jellyfin-ffmpeg"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg".options]
|
||||
asset_pattern = "jellyfin-ffmpeg_*_portable_linuxarm64-gpl.tar.xz"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.linux-arm64"]
|
||||
checksum = "sha256:bea03c670e8cc5bfe9edc0c5d624d4735421610cef5e808db93e7d8596952886"
|
||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_linuxarm64-gpl.tar.xz"
|
||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409048876"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.linux-arm64-musl"]
|
||||
checksum = "sha256:bea03c670e8cc5bfe9edc0c5d624d4735421610cef5e808db93e7d8596952886"
|
||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_linuxarm64-gpl.tar.xz"
|
||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409048876"
|
||||
|
||||
[[tools."github:jellyfin/jellyfin-ffmpeg"]]
|
||||
version = "7.1.3-6"
|
||||
backend = "github:jellyfin/jellyfin-ffmpeg"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg".options]
|
||||
asset_pattern = "jellyfin-ffmpeg_*_portable_linux64-gpl.tar.xz"
|
||||
|
||||
@@ -124,30 +95,6 @@ checksum = "sha256:39e99a7927468a6abec5f65d00f55010e8ff2ae3c2605294f179c94f6ae21
|
||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_linux64-gpl.tar.xz"
|
||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409048879"
|
||||
|
||||
[[tools."github:jellyfin/jellyfin-ffmpeg"]]
|
||||
version = "7.1.3-6"
|
||||
backend = "github:jellyfin/jellyfin-ffmpeg"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg".options]
|
||||
asset_pattern = "jellyfin-ffmpeg_*_portable_mac64-gpl.tar.xz"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.macos-x64"]
|
||||
checksum = "sha256:066ede9774aaae97a18098aaeea8b7e0d286653eb8618f640476e99c59a536c2"
|
||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_mac64-gpl.tar.xz"
|
||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/408995889"
|
||||
|
||||
[[tools."github:jellyfin/jellyfin-ffmpeg"]]
|
||||
version = "7.1.3-6"
|
||||
backend = "github:jellyfin/jellyfin-ffmpeg"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg".options]
|
||||
asset_pattern = "jellyfin-ffmpeg_*_portable_macarm64-gpl.tar.xz"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.macos-arm64"]
|
||||
checksum = "sha256:e024d5e78d5414e75f0181036cd21373fafb9270c72894dfd7dbda2572439820"
|
||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_macarm64-gpl.tar.xz"
|
||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/408995838"
|
||||
|
||||
[[tools."github:webassembly/binaryen"]]
|
||||
version = "version_124"
|
||||
backend = "github:webassembly/binaryen"
|
||||
|
||||
Generated
+8
-3
@@ -3,13 +3,13 @@ Immich API
|
||||
|
||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: 3.0.0-rc.2
|
||||
- Generator version: 7.22.0
|
||||
- API version: 3.0.3
|
||||
- Generator version: 7.24.0
|
||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||
|
||||
## Requirements
|
||||
|
||||
Dart 2.12 or later
|
||||
Dart 2.17 or later
|
||||
|
||||
## Installation & Usage
|
||||
|
||||
@@ -179,6 +179,7 @@ Class | Method | HTTP request | Description
|
||||
*FilesystemApi* | [**getFileListing**](doc//FilesystemApi.md#getfilelisting) | **GET** /yucca/fs |
|
||||
*IntegrationsApi* | [**configureImmichIntegration**](doc//IntegrationsApi.md#configureimmichintegration) | **POST** /yucca/integrations/immich |
|
||||
*IntegrationsApi* | [**getIntegrations**](doc//IntegrationsApi.md#getintegrations) | **GET** /yucca/integrations |
|
||||
*IntegrationsApi* | [**startImmichRollback**](doc//IntegrationsApi.md#startimmichrollback) | **POST** /yucca/integrations/immich/rollback |
|
||||
*JobsApi* | [**createJob**](doc//JobsApi.md#createjob) | **POST** /jobs | Create a manual job
|
||||
*JobsApi* | [**getQueuesLegacy**](doc//JobsApi.md#getqueueslegacy) | **GET** /jobs | Retrieve queue counts and status
|
||||
*JobsApi* | [**runQueueCommandLegacy**](doc//JobsApi.md#runqueuecommandlegacy) | **PUT** /jobs/{name} | Run jobs
|
||||
@@ -503,10 +504,12 @@ Class | Method | HTTP request | Description
|
||||
- [FilesystemListingResponseDto](doc//FilesystemListingResponseDto.md)
|
||||
- [FoldersResponse](doc//FoldersResponse.md)
|
||||
- [FoldersUpdate](doc//FoldersUpdate.md)
|
||||
- [HlsVideoResolution](doc//HlsVideoResolution.md)
|
||||
- [ImageFormat](doc//ImageFormat.md)
|
||||
- [ImmichIntegrationConfigurationDto](doc//ImmichIntegrationConfigurationDto.md)
|
||||
- [ImmichIntegrationDto](doc//ImmichIntegrationDto.md)
|
||||
- [ImmichLibraryDto](doc//ImmichLibraryDto.md)
|
||||
- [ImmichRollbackRequestDto](doc//ImmichRollbackRequestDto.md)
|
||||
- [ImmichStateDto](doc//ImmichStateDto.md)
|
||||
- [ImportRecoveryKeyRequest](doc//ImportRecoveryKeyRequest.md)
|
||||
- [InspectedLocalRepositoryDto](doc//InspectedLocalRepositoryDto.md)
|
||||
@@ -607,6 +610,8 @@ Class | Method | HTTP request | Description
|
||||
- [RatingsUpdate](doc//RatingsUpdate.md)
|
||||
- [ReactionLevel](doc//ReactionLevel.md)
|
||||
- [ReactionType](doc//ReactionType.md)
|
||||
- [RecentlyAddedResponse](doc//RecentlyAddedResponse.md)
|
||||
- [RecentlyAddedUpdate](doc//RecentlyAddedUpdate.md)
|
||||
- [ReleaseChannel](doc//ReleaseChannel.md)
|
||||
- [ReleaseEventV1](doc//ReleaseEventV1.md)
|
||||
- [ReleaseType](doc//ReleaseType.md)
|
||||
|
||||
Generated
+4
@@ -196,10 +196,12 @@ part 'model/filesystem_listing_item_dto.dart';
|
||||
part 'model/filesystem_listing_response_dto.dart';
|
||||
part 'model/folders_response.dart';
|
||||
part 'model/folders_update.dart';
|
||||
part 'model/hls_video_resolution.dart';
|
||||
part 'model/image_format.dart';
|
||||
part 'model/immich_integration_configuration_dto.dart';
|
||||
part 'model/immich_integration_dto.dart';
|
||||
part 'model/immich_library_dto.dart';
|
||||
part 'model/immich_rollback_request_dto.dart';
|
||||
part 'model/immich_state_dto.dart';
|
||||
part 'model/import_recovery_key_request.dart';
|
||||
part 'model/inspected_local_repository_dto.dart';
|
||||
@@ -300,6 +302,8 @@ part 'model/ratings_response.dart';
|
||||
part 'model/ratings_update.dart';
|
||||
part 'model/reaction_level.dart';
|
||||
part 'model/reaction_type.dart';
|
||||
part 'model/recently_added_response.dart';
|
||||
part 'model/recently_added_update.dart';
|
||||
part 'model/release_channel.dart';
|
||||
part 'model/release_event_v1.dart';
|
||||
part 'model/release_type.dart';
|
||||
|
||||
+40
@@ -97,4 +97,44 @@ class IntegrationsApi {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'POST /yucca/integrations/immich/rollback' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [ImmichRollbackRequestDto] immichRollbackRequestDto (required):
|
||||
Future<Response> startImmichRollbackWithHttpInfo(ImmichRollbackRequestDto immichRollbackRequestDto, { Future<void>? abortTrigger, }) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/yucca/integrations/immich/rollback';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = immichRollbackRequestDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
apiPath,
|
||||
'POST',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
abortTrigger: abortTrigger,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [ImmichRollbackRequestDto] immichRollbackRequestDto (required):
|
||||
Future<void> startImmichRollback(ImmichRollbackRequestDto immichRollbackRequestDto, { Future<void>? abortTrigger, }) async {
|
||||
final response = await startImmichRollbackWithHttpInfo(immichRollbackRequestDto, abortTrigger: abortTrigger,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+10
-2
@@ -97,9 +97,9 @@ class ApiClient {
|
||||
if (nullableHeaderParams != null) {
|
||||
request.headers.addAll(nullableHeaderParams);
|
||||
}
|
||||
if (msgBody is String) {
|
||||
if (msgBody is String && msgBody.isNotEmpty) {
|
||||
request.body = msgBody;
|
||||
} else if (msgBody is List<int>) {
|
||||
} else if (msgBody is List<int> && msgBody.isNotEmpty) {
|
||||
request.bodyBytes = msgBody;
|
||||
} else if (msgBody is Map<String, String>) {
|
||||
request.bodyFields = msgBody;
|
||||
@@ -417,6 +417,8 @@ class ApiClient {
|
||||
return FoldersResponse.fromJson(value);
|
||||
case 'FoldersUpdate':
|
||||
return FoldersUpdate.fromJson(value);
|
||||
case 'HlsVideoResolution':
|
||||
return HlsVideoResolutionTypeTransformer().decode(value);
|
||||
case 'ImageFormat':
|
||||
return ImageFormatTypeTransformer().decode(value);
|
||||
case 'ImmichIntegrationConfigurationDto':
|
||||
@@ -425,6 +427,8 @@ class ApiClient {
|
||||
return ImmichIntegrationDto.fromJson(value);
|
||||
case 'ImmichLibraryDto':
|
||||
return ImmichLibraryDto.fromJson(value);
|
||||
case 'ImmichRollbackRequestDto':
|
||||
return ImmichRollbackRequestDto.fromJson(value);
|
||||
case 'ImmichStateDto':
|
||||
return ImmichStateDto.fromJson(value);
|
||||
case 'ImportRecoveryKeyRequest':
|
||||
@@ -625,6 +629,10 @@ class ApiClient {
|
||||
return ReactionLevelTypeTransformer().decode(value);
|
||||
case 'ReactionType':
|
||||
return ReactionTypeTypeTransformer().decode(value);
|
||||
case 'RecentlyAddedResponse':
|
||||
return RecentlyAddedResponse.fromJson(value);
|
||||
case 'RecentlyAddedUpdate':
|
||||
return RecentlyAddedUpdate.fromJson(value);
|
||||
case 'ReleaseChannel':
|
||||
return ReleaseChannelTypeTransformer().decode(value);
|
||||
case 'ReleaseEventV1':
|
||||
|
||||
Generated
+3
@@ -112,6 +112,9 @@ String parameterToString(dynamic value) {
|
||||
if (value is Colorspace) {
|
||||
return ColorspaceTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is HlsVideoResolution) {
|
||||
return HlsVideoResolutionTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is ImageFormat) {
|
||||
return ImageFormatTypeTransformer().encode(value).toString();
|
||||
}
|
||||
|
||||
+24
-20
@@ -11,31 +11,30 @@
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class BackendType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const BackendType._(this.value);
|
||||
enum BackendType {
|
||||
yucca._(r'yucca'),
|
||||
local._(r'local'),
|
||||
s3._(r's3'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const BackendType._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const yucca = BackendType._(r'yucca');
|
||||
static const local = BackendType._(r'local');
|
||||
static const s3 = BackendType._(r's3');
|
||||
|
||||
/// List of all possible values in this [enum][BackendType].
|
||||
static const values = <BackendType>[
|
||||
yucca,
|
||||
local,
|
||||
s3,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [BackendType] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static BackendType? fromJson(dynamic value) => BackendTypeTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [BackendType]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<BackendType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <BackendType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -57,9 +56,11 @@ class BackendTypeTypeTransformer {
|
||||
|
||||
const BackendTypeTypeTransformer._();
|
||||
|
||||
String encode(BackendType data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(BackendType data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a BackendType.
|
||||
/// Returns the instance of [BackendType] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -68,6 +69,9 @@ class BackendTypeTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
BackendType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is BackendType) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'yucca': return BackendType.yucca;
|
||||
@@ -82,7 +86,7 @@ class BackendTypeTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [BackendTypeTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static BackendTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
+24
-20
@@ -11,31 +11,30 @@
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class BootstrapStatus {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const BootstrapStatus._(this.value);
|
||||
enum BootstrapStatus {
|
||||
notReady._(r'not-ready'),
|
||||
ready._(r'ready'),
|
||||
error._(r'error'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const BootstrapStatus._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const notReady = BootstrapStatus._(r'not-ready');
|
||||
static const ready = BootstrapStatus._(r'ready');
|
||||
static const error = BootstrapStatus._(r'error');
|
||||
|
||||
/// List of all possible values in this [enum][BootstrapStatus].
|
||||
static const values = <BootstrapStatus>[
|
||||
notReady,
|
||||
ready,
|
||||
error,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [BootstrapStatus] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static BootstrapStatus? fromJson(dynamic value) => BootstrapStatusTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [BootstrapStatus]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<BootstrapStatus> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <BootstrapStatus>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -57,9 +56,11 @@ class BootstrapStatusTypeTransformer {
|
||||
|
||||
const BootstrapStatusTypeTransformer._();
|
||||
|
||||
String encode(BootstrapStatus data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(BootstrapStatus data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a BootstrapStatus.
|
||||
/// Returns the instance of [BootstrapStatus] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -68,6 +69,9 @@ class BootstrapStatusTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
BootstrapStatus? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is BootstrapStatus) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'not-ready': return BootstrapStatus.notReady;
|
||||
@@ -82,7 +86,7 @@ class BootstrapStatusTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [BootstrapStatusTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static BootstrapStatusTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class ImmichRollbackRequestDto {
|
||||
/// Returns a new [ImmichRollbackRequestDto] instance.
|
||||
ImmichRollbackRequestDto({
|
||||
this.backupFileName = const Optional.absent(),
|
||||
required this.repositoryId,
|
||||
required this.snapshotId,
|
||||
});
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
Optional<String?> backupFileName;
|
||||
|
||||
String repositoryId;
|
||||
|
||||
String snapshotId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is ImmichRollbackRequestDto &&
|
||||
other.backupFileName == backupFileName &&
|
||||
other.repositoryId == repositoryId &&
|
||||
other.snapshotId == snapshotId;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(backupFileName == null ? 0 : backupFileName!.hashCode) +
|
||||
(repositoryId.hashCode) +
|
||||
(snapshotId.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'ImmichRollbackRequestDto[backupFileName=$backupFileName, repositoryId=$repositoryId, snapshotId=$snapshotId]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.backupFileName.isPresent) {
|
||||
final value = this.backupFileName.value;
|
||||
json[r'backupFileName'] = value;
|
||||
}
|
||||
json[r'repositoryId'] = this.repositoryId;
|
||||
json[r'snapshotId'] = this.snapshotId;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [ImmichRollbackRequestDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static ImmichRollbackRequestDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "ImmichRollbackRequestDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return ImmichRollbackRequestDto(
|
||||
backupFileName: json.containsKey(r'backupFileName') ? Optional.present(mapValueOfType<String>(json, r'backupFileName')) : const Optional.absent(),
|
||||
repositoryId: mapValueOfType<String>(json, r'repositoryId')!,
|
||||
snapshotId: mapValueOfType<String>(json, r'snapshotId')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<ImmichRollbackRequestDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <ImmichRollbackRequestDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = ImmichRollbackRequestDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, ImmichRollbackRequestDto> mapFromJson(dynamic json) {
|
||||
final map = <String, ImmichRollbackRequestDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = ImmichRollbackRequestDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of ImmichRollbackRequestDto-objects as value to a dart map
|
||||
static Map<String, List<ImmichRollbackRequestDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<ImmichRollbackRequestDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = ImmichRollbackRequestDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'repositoryId',
|
||||
'snapshotId',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ enum MaintenanceAction {
|
||||
end._(r'end'),
|
||||
selectDatabaseRestore._(r'select_database_restore'),
|
||||
restoreDatabase._(r'restore_database'),
|
||||
rollback._(r'rollback'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
@@ -79,6 +80,7 @@ class MaintenanceActionTypeTransformer {
|
||||
case r'end': return MaintenanceAction.end;
|
||||
case r'select_database_restore': return MaintenanceAction.selectDatabaseRestore;
|
||||
case r'restore_database': return MaintenanceAction.restoreDatabase;
|
||||
case r'rollback': return MaintenanceAction.rollback;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
|
||||
+20
-3
@@ -18,6 +18,7 @@ class MaintenanceStatusResponseDto {
|
||||
this.error = const Optional.absent(),
|
||||
this.progress = const Optional.absent(),
|
||||
this.task = const Optional.absent(),
|
||||
this.yuccaLogId = const Optional.absent(),
|
||||
});
|
||||
|
||||
MaintenanceAction action;
|
||||
@@ -50,13 +51,23 @@ class MaintenanceStatusResponseDto {
|
||||
///
|
||||
Optional<String?> task;
|
||||
|
||||
/// Yucca log ID
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
Optional<String?> yuccaLogId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is MaintenanceStatusResponseDto &&
|
||||
other.action == action &&
|
||||
other.active == active &&
|
||||
other.error == error &&
|
||||
other.progress == progress &&
|
||||
other.task == task;
|
||||
other.task == task &&
|
||||
other.yuccaLogId == yuccaLogId;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
@@ -65,10 +76,11 @@ class MaintenanceStatusResponseDto {
|
||||
(active.hashCode) +
|
||||
(error == null ? 0 : error!.hashCode) +
|
||||
(progress == null ? 0 : progress!.hashCode) +
|
||||
(task == null ? 0 : task!.hashCode);
|
||||
(task == null ? 0 : task!.hashCode) +
|
||||
(yuccaLogId == null ? 0 : yuccaLogId!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'MaintenanceStatusResponseDto[action=$action, active=$active, error=$error, progress=$progress, task=$task]';
|
||||
String toString() => 'MaintenanceStatusResponseDto[action=$action, active=$active, error=$error, progress=$progress, task=$task, yuccaLogId=$yuccaLogId]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
@@ -86,6 +98,10 @@ class MaintenanceStatusResponseDto {
|
||||
final value = this.task.value;
|
||||
json[r'task'] = value;
|
||||
}
|
||||
if (this.yuccaLogId.isPresent) {
|
||||
final value = this.yuccaLogId.value;
|
||||
json[r'yuccaLogId'] = value;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -103,6 +119,7 @@ class MaintenanceStatusResponseDto {
|
||||
error: json.containsKey(r'error') ? Optional.present(mapValueOfType<String>(json, r'error')) : const Optional.absent(),
|
||||
progress: json.containsKey(r'progress') ? Optional.present(json[r'progress'] == null ? null : int.parse('${json[r'progress']}')) : const Optional.absent(),
|
||||
task: json.containsKey(r'task') ? Optional.present(mapValueOfType<String>(json, r'task')) : const Optional.absent(),
|
||||
yuccaLogId: json.containsKey(r'yuccaLogId') ? Optional.present(mapValueOfType<String>(json, r'yuccaLogId')) : const Optional.absent(),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
|
||||
Generated
+24
-20
@@ -11,31 +11,30 @@
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class RunStatus {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const RunStatus._(this.value);
|
||||
enum RunStatus {
|
||||
incomplete._(r'incomplete'),
|
||||
complete._(r'complete'),
|
||||
failed._(r'failed'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const RunStatus._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const incomplete = RunStatus._(r'incomplete');
|
||||
static const complete = RunStatus._(r'complete');
|
||||
static const failed = RunStatus._(r'failed');
|
||||
|
||||
/// List of all possible values in this [enum][RunStatus].
|
||||
static const values = <RunStatus>[
|
||||
incomplete,
|
||||
complete,
|
||||
failed,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [RunStatus] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static RunStatus? fromJson(dynamic value) => RunStatusTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [RunStatus]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<RunStatus> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <RunStatus>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -57,9 +56,11 @@ class RunStatusTypeTransformer {
|
||||
|
||||
const RunStatusTypeTransformer._();
|
||||
|
||||
String encode(RunStatus data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(RunStatus data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a RunStatus.
|
||||
/// Returns the instance of [RunStatus] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -68,6 +69,9 @@ class RunStatusTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
RunStatus? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is RunStatus) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'incomplete': return RunStatus.incomplete;
|
||||
@@ -82,7 +86,7 @@ class RunStatusTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [RunStatusTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static RunStatusTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
Generated
+25
-22
@@ -11,33 +11,31 @@
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class RunType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const RunType._(this.value);
|
||||
enum RunType {
|
||||
schedule._(r'schedule'),
|
||||
restore._(r'restore'),
|
||||
backup._(r'backup'),
|
||||
forget._(r'forget'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const RunType._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const schedule = RunType._(r'schedule');
|
||||
static const restore = RunType._(r'restore');
|
||||
static const backup = RunType._(r'backup');
|
||||
static const forget = RunType._(r'forget');
|
||||
|
||||
/// List of all possible values in this [enum][RunType].
|
||||
static const values = <RunType>[
|
||||
schedule,
|
||||
restore,
|
||||
backup,
|
||||
forget,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [RunType] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static RunType? fromJson(dynamic value) => RunTypeTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [RunType]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<RunType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <RunType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -59,9 +57,11 @@ class RunTypeTypeTransformer {
|
||||
|
||||
const RunTypeTypeTransformer._();
|
||||
|
||||
String encode(RunType data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(RunType data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a RunType.
|
||||
/// Returns the instance of [RunType] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -70,6 +70,9 @@ class RunTypeTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
RunType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is RunType) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'schedule': return RunType.schedule;
|
||||
@@ -85,7 +88,7 @@ class RunTypeTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [RunTypeTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static RunTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
+37
-3
@@ -15,6 +15,8 @@ class SetMaintenanceModeDto {
|
||||
SetMaintenanceModeDto({
|
||||
required this.action,
|
||||
this.restoreBackupFilename = const Optional.absent(),
|
||||
this.rollbackRepositoryId = const Optional.absent(),
|
||||
this.rollbackSnapshotId = const Optional.absent(),
|
||||
});
|
||||
|
||||
MaintenanceAction action;
|
||||
@@ -28,19 +30,41 @@ class SetMaintenanceModeDto {
|
||||
///
|
||||
Optional<String?> restoreBackupFilename;
|
||||
|
||||
/// Rollback repository ID
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
Optional<String?> rollbackRepositoryId;
|
||||
|
||||
/// Rollback snapshot ID
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
Optional<String?> rollbackSnapshotId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is SetMaintenanceModeDto &&
|
||||
other.action == action &&
|
||||
other.restoreBackupFilename == restoreBackupFilename;
|
||||
other.restoreBackupFilename == restoreBackupFilename &&
|
||||
other.rollbackRepositoryId == rollbackRepositoryId &&
|
||||
other.rollbackSnapshotId == rollbackSnapshotId;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(action.hashCode) +
|
||||
(restoreBackupFilename == null ? 0 : restoreBackupFilename!.hashCode);
|
||||
(restoreBackupFilename == null ? 0 : restoreBackupFilename!.hashCode) +
|
||||
(rollbackRepositoryId == null ? 0 : rollbackRepositoryId!.hashCode) +
|
||||
(rollbackSnapshotId == null ? 0 : rollbackSnapshotId!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'SetMaintenanceModeDto[action=$action, restoreBackupFilename=$restoreBackupFilename]';
|
||||
String toString() => 'SetMaintenanceModeDto[action=$action, restoreBackupFilename=$restoreBackupFilename, rollbackRepositoryId=$rollbackRepositoryId, rollbackSnapshotId=$rollbackSnapshotId]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
@@ -49,6 +73,14 @@ class SetMaintenanceModeDto {
|
||||
final value = this.restoreBackupFilename.value;
|
||||
json[r'restoreBackupFilename'] = value;
|
||||
}
|
||||
if (this.rollbackRepositoryId.isPresent) {
|
||||
final value = this.rollbackRepositoryId.value;
|
||||
json[r'rollbackRepositoryId'] = value;
|
||||
}
|
||||
if (this.rollbackSnapshotId.isPresent) {
|
||||
final value = this.rollbackSnapshotId.value;
|
||||
json[r'rollbackSnapshotId'] = value;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -63,6 +95,8 @@ class SetMaintenanceModeDto {
|
||||
return SetMaintenanceModeDto(
|
||||
action: MaintenanceAction.fromJson(json[r'action'])!,
|
||||
restoreBackupFilename: json.containsKey(r'restoreBackupFilename') ? Optional.present(mapValueOfType<String>(json, r'restoreBackupFilename')) : const Optional.absent(),
|
||||
rollbackRepositoryId: json.containsKey(r'rollbackRepositoryId') ? Optional.present(mapValueOfType<String>(json, r'rollbackRepositoryId')) : const Optional.absent(),
|
||||
rollbackSnapshotId: json.containsKey(r'rollbackSnapshotId') ? Optional.present(mapValueOfType<String>(json, r'rollbackSnapshotId')) : const Optional.absent(),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
|
||||
+24
-20
@@ -11,31 +11,30 @@
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class TaskStatus {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const TaskStatus._(this.value);
|
||||
enum TaskStatus {
|
||||
incomplete._(r'incomplete'),
|
||||
complete._(r'complete'),
|
||||
failed._(r'failed'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const TaskStatus._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const incomplete = TaskStatus._(r'incomplete');
|
||||
static const complete = TaskStatus._(r'complete');
|
||||
static const failed = TaskStatus._(r'failed');
|
||||
|
||||
/// List of all possible values in this [enum][TaskStatus].
|
||||
static const values = <TaskStatus>[
|
||||
incomplete,
|
||||
complete,
|
||||
failed,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [TaskStatus] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static TaskStatus? fromJson(dynamic value) => TaskStatusTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [TaskStatus]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<TaskStatus> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <TaskStatus>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -57,9 +56,11 @@ class TaskStatusTypeTransformer {
|
||||
|
||||
const TaskStatusTypeTransformer._();
|
||||
|
||||
String encode(TaskStatus data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(TaskStatus data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a TaskStatus.
|
||||
/// Returns the instance of [TaskStatus] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -68,6 +69,9 @@ class TaskStatusTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
TaskStatus? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is TaskStatus) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'incomplete': return TaskStatus.incomplete;
|
||||
@@ -82,7 +86,7 @@ class TaskStatusTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [TaskStatusTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static TaskStatusTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
Generated
+25
-22
@@ -11,33 +11,31 @@
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class TaskType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const TaskType._(this.value);
|
||||
enum TaskType {
|
||||
schedule._(r'schedule'),
|
||||
restore._(r'restore'),
|
||||
backup._(r'backup'),
|
||||
forget._(r'forget'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const TaskType._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const schedule = TaskType._(r'schedule');
|
||||
static const restore = TaskType._(r'restore');
|
||||
static const backup = TaskType._(r'backup');
|
||||
static const forget = TaskType._(r'forget');
|
||||
|
||||
/// List of all possible values in this [enum][TaskType].
|
||||
static const values = <TaskType>[
|
||||
schedule,
|
||||
restore,
|
||||
backup,
|
||||
forget,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [TaskType] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static TaskType? fromJson(dynamic value) => TaskTypeTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [TaskType]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<TaskType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <TaskType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -59,9 +57,11 @@ class TaskTypeTypeTransformer {
|
||||
|
||||
const TaskTypeTypeTransformer._();
|
||||
|
||||
String encode(TaskType data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(TaskType data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a TaskType.
|
||||
/// Returns the instance of [TaskType] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -70,6 +70,9 @@ class TaskTypeTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
TaskType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is TaskType) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'schedule': return TaskType.schedule;
|
||||
@@ -85,7 +88,7 @@ class TaskTypeTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [TaskTypeTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static TaskTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
+23
-18
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class TelemetryLevel {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const TelemetryLevel._(this.value);
|
||||
enum TelemetryLevel {
|
||||
full._(r'full'),
|
||||
none._(r'none'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const TelemetryLevel._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const full = TelemetryLevel._(r'full');
|
||||
static const none = TelemetryLevel._(r'none');
|
||||
|
||||
/// List of all possible values in this [enum][TelemetryLevel].
|
||||
static const values = <TelemetryLevel>[
|
||||
full,
|
||||
none,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [TelemetryLevel] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static TelemetryLevel? fromJson(dynamic value) => TelemetryLevelTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [TelemetryLevel]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<TelemetryLevel> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <TelemetryLevel>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class TelemetryLevelTypeTransformer {
|
||||
|
||||
const TelemetryLevelTypeTransformer._();
|
||||
|
||||
String encode(TelemetryLevel data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(TelemetryLevel data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a TelemetryLevel.
|
||||
/// Returns the instance of [TelemetryLevel] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class TelemetryLevelTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
TelemetryLevel? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is TelemetryLevel) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'full': return TelemetryLevel.full;
|
||||
@@ -79,7 +84,7 @@ class TelemetryLevelTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [TelemetryLevelTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static TelemetryLevelTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -16399,6 +16399,30 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/yucca/integrations/immich/rollback": {
|
||||
"post": {
|
||||
"operationId": "startImmichRollback",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ImmichRollbackRequestDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Integrations"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/yucca/logs/{id}": {
|
||||
"get": {
|
||||
"operationId": "getRun",
|
||||
@@ -20541,6 +20565,24 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ImmichRollbackRequestDto": {
|
||||
"properties": {
|
||||
"backupFileName": {
|
||||
"type": "string"
|
||||
},
|
||||
"repositoryId": {
|
||||
"type": "string"
|
||||
},
|
||||
"snapshotId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"repositoryId",
|
||||
"snapshotId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ImmichStateDto": {
|
||||
"properties": {
|
||||
"dataFolders": {
|
||||
@@ -21113,7 +21155,8 @@
|
||||
"start",
|
||||
"end",
|
||||
"select_database_restore",
|
||||
"restore_database"
|
||||
"restore_database",
|
||||
"rollback"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
@@ -21198,6 +21241,10 @@
|
||||
},
|
||||
"task": {
|
||||
"type": "string"
|
||||
},
|
||||
"yuccaLogId": {
|
||||
"description": "Yucca log ID",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -25068,6 +25115,14 @@
|
||||
"restoreBackupFilename": {
|
||||
"description": "Restore backup filename",
|
||||
"type": "string"
|
||||
},
|
||||
"rollbackRepositoryId": {
|
||||
"description": "Rollback repository ID",
|
||||
"type": "string"
|
||||
},
|
||||
"rollbackSnapshotId": {
|
||||
"description": "Rollback snapshot ID",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -93,6 +93,10 @@ export type SetMaintenanceModeDto = {
|
||||
action: MaintenanceAction;
|
||||
/** Restore backup filename */
|
||||
restoreBackupFilename?: string;
|
||||
/** Rollback repository ID */
|
||||
rollbackRepositoryId?: string;
|
||||
/** Rollback snapshot ID */
|
||||
rollbackSnapshotId?: string;
|
||||
};
|
||||
export type MaintenanceDetectInstallStorageFolderDto = {
|
||||
/** Number of files in the folder */
|
||||
@@ -120,6 +124,8 @@ export type MaintenanceStatusResponseDto = {
|
||||
error?: string;
|
||||
progress?: number;
|
||||
task?: string;
|
||||
/** Yucca log ID */
|
||||
yuccaLogId?: string;
|
||||
};
|
||||
export type NotificationCreateDto = {
|
||||
/** Additional notification data */
|
||||
@@ -2924,6 +2930,11 @@ export type ConfigureImmichIntegrationRequestDto = {
|
||||
retentionPolicy?: (RetentionPolicyDto) | null;
|
||||
worm: boolean;
|
||||
};
|
||||
export type ImmichRollbackRequestDto = {
|
||||
backupFileName?: string;
|
||||
repositoryId: string;
|
||||
snapshotId: string;
|
||||
};
|
||||
export type RunDto = {
|
||||
end: string;
|
||||
id: string;
|
||||
@@ -7387,6 +7398,15 @@ export function configureImmichIntegration({ configureImmichIntegrationRequestDt
|
||||
body: configureImmichIntegrationRequestDto
|
||||
})));
|
||||
}
|
||||
export function startImmichRollback({ immichRollbackRequestDto }: {
|
||||
immichRollbackRequestDto: ImmichRollbackRequestDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchText("/yucca/integrations/immich/rollback", oazapfts.json({
|
||||
...opts,
|
||||
method: "POST",
|
||||
body: immichRollbackRequestDto
|
||||
})));
|
||||
}
|
||||
export function getRun({ id }: {
|
||||
id: string;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
@@ -7737,7 +7757,8 @@ export enum MaintenanceAction {
|
||||
Start = "start",
|
||||
End = "end",
|
||||
SelectDatabaseRestore = "select_database_restore",
|
||||
RestoreDatabase = "restore_database"
|
||||
RestoreDatabase = "restore_database",
|
||||
Rollback = "rollback"
|
||||
}
|
||||
export enum StorageFolder {
|
||||
EncodedVideo = "encoded-video",
|
||||
|
||||
Generated
+19
-19
@@ -112,8 +112,8 @@ importers:
|
||||
specifier: ^10.1.0
|
||||
version: 10.5.0
|
||||
'@futo-org/backups-orchestrator-ui':
|
||||
specifier: 0.12.0
|
||||
version: 0.12.0(svelte@5.56.5(@typescript-eslint/types@8.64.0))
|
||||
specifier: 0.19.3
|
||||
version: 0.19.3(svelte@5.56.5(@typescript-eslint/types@8.64.0))
|
||||
'@immich/cli':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/cli
|
||||
@@ -404,8 +404,8 @@ importers:
|
||||
specifier: 2.0.0-rc13
|
||||
version: 2.0.0-rc13
|
||||
'@futo-org/backups-orchestrator-api':
|
||||
specifier: 0.12.0
|
||||
version: 0.12.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28)(@nestjs/platform-socket.io@11.1.28)(@nestjs/schedule@6.1.3(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)
|
||||
specifier: 0.19.3
|
||||
version: 0.19.3(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28)(@nestjs/platform-socket.io@11.1.28)(@nestjs/schedule@6.1.3(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)
|
||||
'@immich/plugin-sdk':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/plugin-sdk
|
||||
@@ -798,8 +798,8 @@ importers:
|
||||
specifier: ^3.0.0
|
||||
version: 3.5.15
|
||||
'@futo-org/backups-orchestrator-ui':
|
||||
specifier: 0.12.0
|
||||
version: 0.12.0(@sveltejs/kit@2.69.3(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.5(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)))(@typescript/typescript6@6.0.2)(svelte@5.56.5(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)))(svelte@5.56.5(@typescript-eslint/types@8.64.0))
|
||||
specifier: 0.19.3
|
||||
version: 0.19.3(@sveltejs/kit@2.69.3(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.5(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)))(@typescript/typescript6@6.0.2)(svelte@5.56.5(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)))(svelte@5.56.5(@typescript-eslint/types@8.64.0))
|
||||
'@immich/justified-layout-wasm':
|
||||
specifier: ^0.4.3
|
||||
version: 0.4.3
|
||||
@@ -2907,11 +2907,11 @@ packages:
|
||||
resolution: {integrity: sha512-YTVITFGN0/24PxzXrwqCgnyd7njDuzp5ZvaCx5nq/jg55kUYd94Nj8UTchBdBofi/L0nwRfjGOg0E41d2u9T1w==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
'@futo-org/backups-api-client@0.12.0':
|
||||
resolution: {integrity: sha512-DJ+XJusy8h6qCYyQUKZvY1nvLfvf8OgLIBphIV5MbcPmbBR5oLQcfyVgiyXCjWmGnbnNi8YIDiE07nerWqWfeg==}
|
||||
'@futo-org/backups-api-client@0.19.3':
|
||||
resolution: {integrity: sha512-aaZ/bQF2eDFrkSjRadziO6+ZrcRpdupelxwF2UusMp/WyQQCC0Qo3d59Ok5YnMxuC0iS2Kz3aDBNZqnqweBtGw==}
|
||||
|
||||
'@futo-org/backups-orchestrator-api@0.12.0':
|
||||
resolution: {integrity: sha512-8wC5gbkL3yG0gZh90vh9j1IgOf6DlsT1beqVVP3qe84cIyC0yvd4GoDiBK1ymMEfXElqVSV8vV8KgjtKWb6MbA==}
|
||||
'@futo-org/backups-orchestrator-api@0.19.3':
|
||||
resolution: {integrity: sha512-ZEMVvtgTdwvEhiZRLVUSj4c+6vFifV0sMrXkOq1o9i19NR+jTq6BtfancJ5HnJL47zTmWHYDewgUzjMO4EqoKg==}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^11.0.0
|
||||
'@nestjs/core': ^11.0.0
|
||||
@@ -2919,8 +2919,8 @@ packages:
|
||||
'@nestjs/schedule': ^6.0.0
|
||||
'@nestjs/websockets': ^11.0.0
|
||||
|
||||
'@futo-org/backups-orchestrator-ui@0.12.0':
|
||||
resolution: {integrity: sha512-nrGQKBdkGitvfL78P5wu0ITaOykbIQEbbUJyuLIYE6yhqH0hX6/u1WlnRoTfcXJeat3Qt+3/W4ayUYr1qOOpmA==}
|
||||
'@futo-org/backups-orchestrator-ui@0.19.3':
|
||||
resolution: {integrity: sha512-3fA4hTIrdESm1MqN9pddBnZndn2oAcHQPcLBslhR0TJbgeujSRl3/7jWu9q7reTeq/r4oDPxQecTLo66C1v6DQ==}
|
||||
peerDependencies:
|
||||
svelte: ^5.0.0
|
||||
|
||||
@@ -15974,13 +15974,13 @@ snapshots:
|
||||
dependencies:
|
||||
'@fortawesome/fontawesome-common-types': 7.2.0
|
||||
|
||||
'@futo-org/backups-api-client@0.12.0':
|
||||
'@futo-org/backups-api-client@0.19.3':
|
||||
dependencies:
|
||||
'@oazapfts/runtime': 1.2.0
|
||||
|
||||
'@futo-org/backups-orchestrator-api@0.12.0(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28)(@nestjs/platform-socket.io@11.1.28)(@nestjs/schedule@6.1.3(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)':
|
||||
'@futo-org/backups-orchestrator-api@0.19.3(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28)(@nestjs/platform-socket.io@11.1.28)(@nestjs/schedule@6.1.3(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.28))(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)':
|
||||
dependencies:
|
||||
'@futo-org/backups-api-client': 0.12.0
|
||||
'@futo-org/backups-api-client': 0.19.3
|
||||
'@futo-org/restic-wrapper': 1.3.0
|
||||
'@nestjs/common': 11.1.28(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||
'@nestjs/core': 11.1.28(@nestjs/common@11.1.28(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.28)(@nestjs/websockets@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||
@@ -16007,9 +16007,9 @@ snapshots:
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
'@futo-org/backups-orchestrator-ui@0.12.0(@sveltejs/kit@2.69.3(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.5(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)))(@typescript/typescript6@6.0.2)(svelte@5.56.5(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)))(svelte@5.56.5(@typescript-eslint/types@8.64.0))':
|
||||
'@futo-org/backups-orchestrator-ui@0.19.3(@sveltejs/kit@2.69.3(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.5(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)))(@typescript/typescript6@6.0.2)(svelte@5.56.5(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)))(svelte@5.56.5(@typescript-eslint/types@8.64.0))':
|
||||
dependencies:
|
||||
'@futo-org/backups-api-client': 0.12.0
|
||||
'@futo-org/backups-api-client': 0.19.3
|
||||
'@immich/ui': 0.59.0(@sveltejs/kit@2.69.3(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.2.0(svelte@5.56.5(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)))(@typescript/typescript6@6.0.2)(svelte@5.56.5(@typescript-eslint/types@8.64.0))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass@1.101.0)(terser@5.49.0)(tsx@4.23.1)(yaml@2.9.0)))(svelte@5.56.5(@typescript-eslint/types@8.64.0))
|
||||
'@mdi/js': 7.4.47
|
||||
'@oazapfts/runtime': 1.2.0
|
||||
@@ -16026,9 +16026,9 @@ snapshots:
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
'@futo-org/backups-orchestrator-ui@0.12.0(svelte@5.56.5(@typescript-eslint/types@8.64.0))':
|
||||
'@futo-org/backups-orchestrator-ui@0.19.3(svelte@5.56.5(@typescript-eslint/types@8.64.0))':
|
||||
dependencies:
|
||||
'@futo-org/backups-api-client': 0.12.0
|
||||
'@futo-org/backups-api-client': 0.19.3
|
||||
'@immich/ui': 0.59.0(svelte@5.56.5(@typescript-eslint/types@8.64.0))
|
||||
'@mdi/js': 7.4.47
|
||||
'@oazapfts/runtime': 1.2.0
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@extism/extism": "2.0.0-rc13",
|
||||
"@futo-org/backups-orchestrator-api": "0.12.0",
|
||||
"@futo-org/backups-orchestrator-api": "0.19.3",
|
||||
"@immich/plugin-sdk": "workspace:*",
|
||||
"@immich/sql-tools": "^0.5.1",
|
||||
"@nestjs/bullmq": "^11.0.1",
|
||||
|
||||
@@ -27,6 +27,8 @@ const DatabaseBackupDeleteSchema = z
|
||||
})
|
||||
.meta({ id: 'DatabaseBackupDeleteDto' });
|
||||
|
||||
export type DatabaseBackupDto = z.infer<typeof DatabaseBackupSchema>;
|
||||
|
||||
export class DatabaseBackupListResponseDto extends createZodDto(DatabaseBackupListResponseSchema) {}
|
||||
export class DatabaseBackupUploadDto extends createZodDto(DatabaseBackupUploadSchema) {}
|
||||
export class DatabaseBackupDeleteDto extends createZodDto(DatabaseBackupDeleteSchema) {}
|
||||
|
||||
@@ -6,6 +6,8 @@ const SetMaintenanceModeSchema = z
|
||||
.object({
|
||||
action: MaintenanceActionSchema,
|
||||
restoreBackupFilename: z.string().optional().describe('Restore backup filename'),
|
||||
rollbackRepositoryId: z.string().optional().describe('Rollback repository ID'),
|
||||
rollbackSnapshotId: z.string().optional().describe('Rollback snapshot ID'),
|
||||
})
|
||||
.refine(
|
||||
(data) => data.action !== MaintenanceAction.RestoreDatabase || (data.restoreBackupFilename?.length ?? 0) > 0,
|
||||
@@ -32,6 +34,7 @@ const MaintenanceStatusResponseSchema = z
|
||||
progress: z.int().optional(),
|
||||
task: z.string().optional(),
|
||||
error: z.string().optional(),
|
||||
yuccaLogId: z.string().optional().describe('Yucca log ID'),
|
||||
})
|
||||
.meta({ id: 'MaintenanceStatusResponseDto' });
|
||||
|
||||
|
||||
@@ -977,6 +977,7 @@ export enum MaintenanceAction {
|
||||
End = 'end',
|
||||
SelectDatabaseRestore = 'select_database_restore',
|
||||
RestoreDatabase = 'restore_database',
|
||||
Rollback = 'rollback',
|
||||
}
|
||||
|
||||
export const MaintenanceActionSchema = z
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { YuccaService } from '@futo-org/backups-orchestrator-api';
|
||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { ModuleRef } from '@nestjs/core';
|
||||
import { parse } from 'cookie';
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
import { jwtVerify } from 'jose';
|
||||
@@ -30,6 +32,7 @@ import { type ServerService as _ServerService } from 'src/services/server.servic
|
||||
import { type VersionService as _VersionService } from 'src/services/version.service';
|
||||
import { MaintenanceModeState } from 'src/types';
|
||||
import { getConfig } from 'src/utils/config';
|
||||
import { getLatestDatabaseBackup } from 'src/utils/database-backups';
|
||||
import { createMaintenanceLoginUrl, detectPriorInstall } from 'src/utils/maintenance';
|
||||
import { getExternalDomain } from 'src/utils/misc';
|
||||
import { detectMediaLocation } from 'src/utils/storage';
|
||||
@@ -56,6 +59,7 @@ export class MaintenanceWorkerService {
|
||||
private processRepository: ProcessRepository,
|
||||
private databaseRepository: DatabaseRepository,
|
||||
private databaseBackupService: DatabaseBackupService,
|
||||
private moduleRef: ModuleRef,
|
||||
) {
|
||||
this.logger.setContext(this.constructor.name);
|
||||
}
|
||||
@@ -271,6 +275,9 @@ export class MaintenanceWorkerService {
|
||||
case MaintenanceAction.RestoreDatabase: {
|
||||
return this.runRestoreDatabase(action);
|
||||
}
|
||||
case MaintenanceAction.Rollback: {
|
||||
return this.runRollback(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,6 +336,67 @@ export class MaintenanceWorkerService {
|
||||
});
|
||||
}
|
||||
|
||||
private async runRollback(action: SetMaintenanceModeDto) {
|
||||
const isLock = await this.databaseRepository.tryLock(DatabaseLock.MaintenanceOperation);
|
||||
if (!isLock) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.log(`Running maintenance action ${action.action}`);
|
||||
|
||||
await this.systemMetadataRepository.set(SystemMetadataKey.MaintenanceMode, {
|
||||
isMaintenanceMode: true,
|
||||
secret: this.secret,
|
||||
action: {
|
||||
action: MaintenanceAction.Start,
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
if (!action.rollbackRepositoryId || !action.rollbackSnapshotId) {
|
||||
throw new Error("Expected rollbackRepositoryId and rollbackSnapshotId but they're missing!");
|
||||
}
|
||||
|
||||
await this.rollback(action.rollbackRepositoryId, action.rollbackSnapshotId);
|
||||
} catch (error) {
|
||||
this.logger.error(`Encountered error running action: ${error}`);
|
||||
this.setStatus({
|
||||
active: true,
|
||||
action: action.action,
|
||||
task: 'error',
|
||||
error: '' + error,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async rollback(repositoryId: string, snapshotId: string): Promise<void> {
|
||||
this.setStatus({
|
||||
active: true,
|
||||
action: MaintenanceAction.Rollback,
|
||||
});
|
||||
|
||||
const yucca = this.moduleRef.get(YuccaService, { strict: false });
|
||||
const { logId, task } = await yucca.restoreSnapshotInplace(repositoryId, snapshotId);
|
||||
|
||||
this.setStatus({
|
||||
active: true,
|
||||
action: MaintenanceAction.Rollback,
|
||||
yuccaLogId: logId,
|
||||
});
|
||||
|
||||
await task;
|
||||
|
||||
const { backups } = await this.databaseBackupService.listBackups();
|
||||
const latest = getLatestDatabaseBackup(backups);
|
||||
if (!latest) {
|
||||
return this.setAction({
|
||||
action: MaintenanceAction.SelectDatabaseRestore,
|
||||
});
|
||||
}
|
||||
|
||||
await this.restoreBackup(latest.filename);
|
||||
}
|
||||
|
||||
private async endMaintenance(): Promise<void> {
|
||||
const state: MaintenanceModeState = { isMaintenanceMode: false as const };
|
||||
await this.systemMetadataRepository.set(SystemMetadataKey.MaintenanceMode, state);
|
||||
|
||||
@@ -3,10 +3,12 @@ import { Injectable, Optional } from '@nestjs/common';
|
||||
import { SystemConfig } from 'src/config';
|
||||
import { StorageCore } from 'src/cores/storage.core';
|
||||
import { OnEvent } from 'src/decorators';
|
||||
import { DatabaseLock, ImmichWorker, StorageFolder } from 'src/enum';
|
||||
import { DatabaseLock, ImmichWorker, MaintenanceAction, StorageFolder } from 'src/enum';
|
||||
import { DatabaseRepository } from 'src/repositories/database.repository';
|
||||
import { ArgOf } from 'src/repositories/event.repository';
|
||||
import { LibraryRepository } from 'src/repositories/library.repository';
|
||||
import { DatabaseBackupService } from 'src/services/database-backup.service';
|
||||
import { MaintenanceService } from 'src/services/maintenance.service';
|
||||
import { getExternalDomain } from 'src/utils/misc';
|
||||
|
||||
@Injectable()
|
||||
@@ -14,8 +16,13 @@ export class YuccaService {
|
||||
constructor(
|
||||
private readonly databaseRepository: DatabaseRepository,
|
||||
private readonly libraryRepository: LibraryRepository,
|
||||
private readonly databaseBackupService: DatabaseBackupService,
|
||||
@Optional() private readonly maintenanceService: MaintenanceService,
|
||||
@Optional() private readonly yuccaService: YuccaOrchestratorService,
|
||||
) {}
|
||||
) {
|
||||
this.createDatabaseBackup = this.createDatabaseBackup.bind(this);
|
||||
this.enterMaintenanceRollback = this.enterMaintenanceRollback.bind(this);
|
||||
}
|
||||
|
||||
private updateSystemConfig({ server }: SystemConfig) {
|
||||
this.yuccaService.setExternalBaseUrl(getExternalDomain(server));
|
||||
@@ -30,9 +37,28 @@ export class YuccaService {
|
||||
libraries: libraries
|
||||
.filter((library) => !library.deletedAt)
|
||||
.map(({ id, name, importPaths, exclusionPatterns }) => ({ id, name, importPaths, exclusionPatterns })),
|
||||
hooks: {
|
||||
createDatabaseBackup: this.createDatabaseBackup,
|
||||
enterMaintenanceRollback: this.enterMaintenanceRollback,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private async createDatabaseBackup() {
|
||||
await this.databaseBackupService.createDatabaseBackup();
|
||||
}
|
||||
|
||||
private enterMaintenanceRollback(repositoryId: string, snapshotId: string) {
|
||||
return this.maintenanceService.startMaintenance(
|
||||
{
|
||||
action: MaintenanceAction.Rollback,
|
||||
rollbackRepositoryId: repositoryId,
|
||||
rollbackSnapshotId: snapshotId,
|
||||
},
|
||||
'yucca-rollback',
|
||||
);
|
||||
}
|
||||
|
||||
@OnEvent({ name: 'ConfigInit', workers: [ImmichWorker.Api] })
|
||||
async onConfigInit({ newConfig }: ArgOf<'ConfigInit'>) {
|
||||
this.updateSystemConfig(newConfig);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { DateTime } from 'luxon';
|
||||
import { DatabaseBackupDto } from 'src/dtos/database-backup.dto';
|
||||
|
||||
export function isValidDatabaseBackupName(filename: string) {
|
||||
return filename.match(/^[\d\w-.]+\.sql(?:\.gz)?$/);
|
||||
}
|
||||
@@ -17,6 +20,23 @@ export function findDatabaseBackupVersion(filename: string) {
|
||||
return /-v(.*)-/.exec(filename)?.[1];
|
||||
}
|
||||
|
||||
function getDatabaseBackupTimestamp(backup: DatabaseBackupDto): number {
|
||||
const dateMatch = backup.filename.match(/\d+T\d+/);
|
||||
if (!dateMatch) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DateTime.fromFormat(dateMatch[0], "yyyyMMdd'T'HHmmss", { zone: backup.timezone }).toMillis();
|
||||
}
|
||||
|
||||
export function getLatestDatabaseBackup<T extends DatabaseBackupDto>(backups: T[]): T | undefined {
|
||||
if (backups.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return backups.toSorted((a, b) => getDatabaseBackupTimestamp(b) - getDatabaseBackupTimestamp(a))[0];
|
||||
}
|
||||
|
||||
export class UnsupportedPostgresError extends Error {
|
||||
constructor(databaseVersion: string) {
|
||||
super(`Unsupported PostgreSQL version: ${databaseVersion}`);
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@formatjs/icu-messageformat-parser": "^3.0.0",
|
||||
"@futo-org/backups-orchestrator-ui": "0.12.0",
|
||||
"@futo-org/backups-orchestrator-ui": "0.19.3",
|
||||
"@immich/justified-layout-wasm": "^0.4.3",
|
||||
"@immich/sdk": "workspace:*",
|
||||
"@immich/ui": "^0.83.0",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { maintenanceStore } from '$lib/stores/maintenance.store';
|
||||
import { MaintenanceAction } from '@immich/sdk';
|
||||
import { Button, Heading, Link, ProgressBar, Scrollable, Text } from '@immich/ui';
|
||||
import { YuccaContext } from '@futo-org/backups-orchestrator-ui';
|
||||
import { YuccaContext, ViewLogModal } from '@futo-org/backups-orchestrator-ui';
|
||||
import { t } from 'svelte-i18n';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
@@ -72,6 +72,8 @@
|
||||
<Text>{$t('maintenance_task_rollback')}</Text>
|
||||
{/if}
|
||||
{/if}
|
||||
{:else if $status?.action === MaintenanceAction.Rollback}
|
||||
<ViewLogModal logId={$status!.yuccaLogId} onClose={() => void 0} />
|
||||
{:else if $status?.action === MaintenanceAction.SelectDatabaseRestore && $auth}
|
||||
<MaintenanceRestoreFlow {end} expectedVersion={data.expectedVersion} />
|
||||
{:else}
|
||||
|
||||
Reference in New Issue
Block a user