Files
2026-07-13 12:30:28 +08:00

147 lines
5.5 KiB
TypeScript

import chalk from 'chalk';
import inquirer from 'inquirer';
import axios from 'axios';
import fs from 'fs-extra';
import path from 'path';
import { getAuthHeaders } from './utils/webLogin';
import { getPinmeApiUrl } from './utils/config';
import tracker, { getTrackErrorReason } from './utils/tracker';
import {
TRACK_EVENTS,
TRACK_PAGES,
resolveTrackAction,
} from './utils/trackerEvents';
interface DeleteOptions {
name?: string;
force?: boolean;
}
// 从 pinme.toml 获取项目名
function getProjectName(): string | null {
const configPath = path.join(process.cwd(), 'pinme.toml');
if (!fs.existsSync(configPath)) {
return null;
}
const config = fs.readFileSync(configPath, 'utf-8');
const match = config.match(/project_name\s*=\s*"([^"]+)"/);
return match?.[1] || null;
}
/**
* Delete a project: removes Worker domain binding, Worker script, D1 database
*/
export default async function deleteCmd(options: DeleteOptions): Promise<void> {
try {
// Check if user is logged in
const headers = getAuthHeaders();
if (!headers['authentication-tokens'] || !headers['token-address']) {
console.log(chalk.yellow('\n⚠️ You are not logged in.'));
console.log(chalk.gray('Please run: pinme login'));
process.exit(1);
}
console.log(chalk.blue('Deleting project...\n'));
// Get project name from pinme.toml or options
let projectName = options.name || getProjectName();
if (!projectName) {
console.log(chalk.red('\n❌ Error: Cannot find project name.'));
console.log(chalk.yellow(' Please make sure you are in the project directory.'));
console.log(chalk.gray(' The project directory should contain a pinme.toml file.'));
console.log(chalk.gray('\n Or specify the project name:'));
console.log(chalk.gray(' cd /path/to/your-project'));
console.log(chalk.gray(' pinme delete'));
process.exit(1);
}
console.log(chalk.gray(`Project: ${projectName}`));
console.log(chalk.gray(`Directory: ${process.cwd()}`));
// Confirm deletion
if (!options.force) {
const answers = await inquirer.prompt([
{
type: 'confirm',
name: 'confirm',
message: `Are you sure you want to delete project "${projectName}"? This will remove Worker, domain binding, and D1 database.`,
default: false,
},
]);
if (!answers.confirm) {
console.log(chalk.gray('Cancelled.'));
process.exit(0);
}
}
// Call API to delete project
console.log(chalk.blue('Deleting project on platform...'));
const apiUrl = getPinmeApiUrl('/delete_project');
console.log(chalk.gray(`API URL: ${apiUrl}`));
console.log(chalk.gray(`Project name: ${projectName}`));
const response = await axios.post(apiUrl, {
project_name: projectName,
}, {
headers: {
...headers,
'Content-Type': 'application/json',
},
}).catch((error) => {
if (error.response) {
console.log(chalk.red(` Response status: ${error.response?.status}`));
console.log(chalk.red(` Response data: ${JSON.stringify(error.response?.data)}`));
} else {
console.log(chalk.red('No Response'))
}
throw error;
});
const data = response.data;
if (data.code === 200) {
void tracker.trackEvent(
TRACK_EVENTS.projectDeleteSuccess,
TRACK_PAGES.project,
{
a: resolveTrackAction(TRACK_EVENTS.projectDeleteSuccess),
project_name: data.data.project_name,
domain_deleted: Boolean(data.data.domain_deleted),
worker_deleted: Boolean(data.data.worker_deleted),
database_deleted: Boolean(data.data.database_deleted),
},
);
console.log(chalk.green('\n✅ Project deleted successfully!'));
console.log(chalk.gray(`\nProject: ${data.data.project_name}`));
console.log(chalk.gray(` Domain deleted: ${data.data.domain_deleted ? '✅' : '❌'}`));
console.log(chalk.gray(` Worker deleted: ${data.data.worker_deleted ? '✅' : '❌'}`));
console.log(chalk.gray(` Database deleted: ${data.data.database_deleted ? '✅' : '❌'}`));
console.log(chalk.gray('\nLocal files are kept unchanged.'));
} else {
const errorMsg = data?.msg || 'Failed to delete project';
throw new Error(errorMsg);
}
process.exit(0);
} catch (error: any) {
void tracker.trackEvent(
TRACK_EVENTS.projectDeleteFailed,
TRACK_PAGES.project,
{
a: resolveTrackAction(TRACK_EVENTS.projectDeleteFailed),
project_name: options.name || getProjectName() || undefined,
force: Boolean(options.force),
reason: getTrackErrorReason(error),
},
);
console.log(chalk.red(error));
const errorMsg = error.response?.data?.msg
|| error.message
|| 'Failed to delete project';
console.error(chalk.red(`\n❌ Error: ${errorMsg}`));
process.exit(1);
}
}