mirror of
https://github.com/immich-app/immich.git
synced 2025-12-20 17:25:35 +03:00
@@ -1,11 +1,16 @@
|
||||
import { GrantAdminCommand, PromptEmailQuestion, RevokeAdminCommand } from 'src/commands/grant-admin';
|
||||
import { ListUsersCommand } from 'src/commands/list-users.command';
|
||||
import {
|
||||
ChangeMediaLocationCommand,
|
||||
PromptConfirmMoveQuestions,
|
||||
PromptMediaLocationQuestions,
|
||||
} from 'src/commands/media-location.command';
|
||||
import { DisableOAuthLogin, EnableOAuthLogin } from 'src/commands/oauth-login';
|
||||
import { DisablePasswordLoginCommand, EnablePasswordLoginCommand } from 'src/commands/password-login';
|
||||
import { PromptPasswordQuestions, ResetAdminPasswordCommand } from 'src/commands/reset-admin-password.command';
|
||||
import { VersionCommand } from 'src/commands/version.command';
|
||||
|
||||
export const commands = [
|
||||
export const commandsAndQuestions = [
|
||||
ResetAdminPasswordCommand,
|
||||
PromptPasswordQuestions,
|
||||
PromptEmailQuestion,
|
||||
@@ -17,4 +22,7 @@ export const commands = [
|
||||
VersionCommand,
|
||||
GrantAdminCommand,
|
||||
RevokeAdminCommand,
|
||||
ChangeMediaLocationCommand,
|
||||
PromptMediaLocationQuestions,
|
||||
PromptConfirmMoveQuestions,
|
||||
];
|
||||
|
||||
106
server/src/commands/media-location.command.ts
Normal file
106
server/src/commands/media-location.command.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { Command, CommandRunner, InquirerService, Question, QuestionSet } from 'nest-commander';
|
||||
import { CliService } from 'src/services/cli.service';
|
||||
|
||||
@Command({
|
||||
name: 'change-media-location',
|
||||
description: 'Change database file paths to align with a new media location',
|
||||
})
|
||||
export class ChangeMediaLocationCommand extends CommandRunner {
|
||||
constructor(
|
||||
private service: CliService,
|
||||
private inquirer: InquirerService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
private async showSamplePaths(hint?: string) {
|
||||
hint = hint ? ` (${hint})` : '';
|
||||
|
||||
const paths = await this.service.getSampleFilePaths();
|
||||
if (paths.length > 0) {
|
||||
let message = ` Examples from the database${hint}:\n`;
|
||||
for (const path of paths) {
|
||||
message += ` - ${path}\n`;
|
||||
}
|
||||
|
||||
console.log(`\n${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
try {
|
||||
await this.showSamplePaths();
|
||||
|
||||
const { oldValue, newValue } = await this.inquirer.ask<{ oldValue: string; newValue: string }>(
|
||||
'prompt-media-location',
|
||||
{},
|
||||
);
|
||||
|
||||
const success = await this.service.migrateFilePaths({
|
||||
oldValue,
|
||||
newValue,
|
||||
confirm: async ({ sourceFolder, targetFolder }) => {
|
||||
console.log(`
|
||||
Previous value: ${oldValue}
|
||||
Current value: ${newValue}
|
||||
|
||||
Changing from "${sourceFolder}/*" to "${targetFolder}/*"
|
||||
`);
|
||||
|
||||
const { value: confirmed } = await this.inquirer.ask<{ value: boolean }>('prompt-confirm-move', {});
|
||||
return confirmed;
|
||||
},
|
||||
});
|
||||
|
||||
const successMessage = `Matching database file paths were updated successfully! 🎉
|
||||
|
||||
You may now set IMMICH_MEDIA_LOCATION=${newValue} and restart!
|
||||
|
||||
(please remember to update applicable volume mounts e.g
|
||||
services:
|
||||
immich-server:
|
||||
...
|
||||
volumes:
|
||||
- \${UPLOAD_LOCATION}:/usr/src/app/upload
|
||||
...
|
||||
)`;
|
||||
|
||||
console.log(`\n ${success ? successMessage : 'No rows were updated'}\n`);
|
||||
|
||||
await this.showSamplePaths('after');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error('Unable to update database file paths.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const currentValue = process.env.IMMICH_MEDIA_LOCATION || '';
|
||||
|
||||
const makePrompt = (which: string) => {
|
||||
return `Enter the ${which} value of IMMICH_MEDIA_LOCATION:${currentValue ? ` [${currentValue}]` : ''}`;
|
||||
};
|
||||
|
||||
@QuestionSet({ name: 'prompt-media-location' })
|
||||
export class PromptMediaLocationQuestions {
|
||||
@Question({ message: makePrompt('previous'), name: 'oldValue' })
|
||||
oldValue(value: string) {
|
||||
return value || currentValue;
|
||||
}
|
||||
|
||||
@Question({ message: makePrompt('new'), name: 'newValue' })
|
||||
newValue(value: string) {
|
||||
return value || currentValue;
|
||||
}
|
||||
}
|
||||
|
||||
@QuestionSet({ name: 'prompt-confirm-move' })
|
||||
export class PromptConfirmMoveQuestions {
|
||||
@Question({
|
||||
message: 'Do you want to proceed? [Y/n]',
|
||||
name: 'value',
|
||||
})
|
||||
value(value: string): boolean {
|
||||
return ['yes', 'y'].includes((value || 'y').toLowerCase());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user