Files
AFFiNE-Mirror/packages/backend/server/src/cli.ts
T
DarkSky d3ec008b0c chore: bump deps (#14777)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Migration and config commands now feature interactive prompts for
required inputs.

* **Bug Fixes**
  * Enhanced error handling in CLI operations.

* **Chores**
  * Updated GraphQL Code Generator toolchain to v6.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-03 19:36:18 +08:00

103 lines
2.5 KiB
TypeScript

import { basename } from 'node:path';
import { type INestApplicationContext, Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { Command, CommanderError } from 'commander';
import { CliAppModule } from './data/app';
import { CreateCommand } from './data/commands/create';
import { ImportConfigCommand } from './data/commands/import';
import { RevertCommand, RunCommand } from './data/commands/run';
function getProgramName() {
return process.env.npm_lifecycle_event ?? basename(process.argv[1] ?? 'cli');
}
async function withCliApp(
logger: Logger,
callback: (app: INestApplicationContext) => Promise<void>
) {
const app = await NestFactory.createApplicationContext(CliAppModule, {
logger,
});
try {
await callback(app);
} finally {
await app.close();
}
}
function buildProgram(logger: Logger) {
const program = new Command();
program
.name(getProgramName())
.description('AFFiNE server CLI')
.showHelpAfterError()
.showSuggestionAfterError();
program
.command('create [name]')
.description('create a data migration script')
.action(async name => {
await withCliApp(logger, async app => {
await app.get(CreateCommand).execute(name);
});
});
program
.command('run')
.description('Run all pending data migrations')
.action(async () => {
await withCliApp(logger, async app => {
await app.get(RunCommand).execute();
});
});
program
.command('revert [name]')
.description('Revert one data migration with given name')
.action(async name => {
await withCliApp(logger, async app => {
await app.get(RevertCommand).execute(name);
});
});
program
.command('import-config [path]')
.description('import config from a file')
.action(async path => {
await withCliApp(logger, async app => {
await app.get(ImportConfigCommand).execute(path);
});
});
return program;
}
export async function run() {
const logger = new Logger('Cli');
try {
const program = buildProgram(logger);
program.exitOverride();
const argv =
process.argv.length > 2 ? process.argv : [...process.argv, '--help'];
await program.parseAsync(argv);
} catch (error) {
if (error instanceof CommanderError) {
process.exitCode = error.exitCode;
return;
}
if (error instanceof Error) {
logger.error(error.message, error.stack);
} else {
logger.error(String(error));
}
process.exitCode = 1;
}
}