@@ -15,8 +15,7 @@ export class AppBuildCommand {
|
||||
await checkSdkVersionCompatibility(appPath);
|
||||
|
||||
console.log(chalk.blue('Building application...'));
|
||||
console.log(chalk.gray(`App path: ${appPath}`));
|
||||
console.log('');
|
||||
console.log(chalk.gray(`App path: ${appPath}\n`));
|
||||
|
||||
const result = await appBuild({
|
||||
appPath,
|
||||
|
||||
@@ -36,8 +36,7 @@ export class DeployCommand {
|
||||
const remoteName = options.remote ?? ConfigService.getActiveRemote();
|
||||
|
||||
console.log(chalk.blue(`Deploying to ${remoteName} (${serverUrl})...`));
|
||||
console.log(chalk.gray(`App path: ${appPath}`));
|
||||
console.log('');
|
||||
console.log(chalk.gray(`App path: ${appPath}\n`));
|
||||
|
||||
const result = await appDeploy({
|
||||
appPath,
|
||||
|
||||
@@ -33,8 +33,7 @@ export class LogicFunctionExecuteCommand {
|
||||
: (functionUniversalIdentifier ?? functionName);
|
||||
|
||||
console.log(chalk.blue(`🚀 Executing function "${identifier}"...`));
|
||||
console.log(chalk.gray(` Payload: ${JSON.stringify(parsedPayload)}`));
|
||||
console.log('');
|
||||
console.log(chalk.gray(` Payload: ${JSON.stringify(parsedPayload)}\n`));
|
||||
|
||||
const executeOptions = postInstall
|
||||
? { appPath, postInstall: true as const, payload: parsedPayload }
|
||||
@@ -58,8 +57,7 @@ export class LogicFunctionExecuteCommand {
|
||||
break;
|
||||
}
|
||||
case FUNCTION_ERROR_CODES.FUNCTION_NOT_FOUND: {
|
||||
console.error(chalk.red(result.error.message));
|
||||
console.log('');
|
||||
console.error(chalk.red(result.error.message), '\n');
|
||||
|
||||
const availableFunctions = (result.error.details
|
||||
?.availableFunctions ?? []) as Array<{
|
||||
@@ -106,30 +104,26 @@ export class LogicFunctionExecuteCommand {
|
||||
`${chalk.bold('Status:')} ${statusColor(executionResult.status)}`,
|
||||
);
|
||||
|
||||
console.log(`${chalk.bold('Duration:')} ${executionResult.duration}ms`);
|
||||
console.log(`${chalk.bold('Duration:')} ${executionResult.duration}ms\n`);
|
||||
|
||||
if (isDefined(executionResult.data)) {
|
||||
console.log('');
|
||||
console.log(chalk.bold('Data:'));
|
||||
console.log(chalk.white(JSON.stringify(executionResult.data, null, 2)));
|
||||
}
|
||||
|
||||
if (executionResult.error) {
|
||||
console.log('');
|
||||
console.log(chalk.bold.red('Error:'));
|
||||
console.log(chalk.red(` Type: ${executionResult.error.errorType}`));
|
||||
console.log(
|
||||
chalk.red(` Message: ${executionResult.error.errorMessage}`),
|
||||
chalk.red(` Message: ${executionResult.error.errorMessage}\n`),
|
||||
);
|
||||
if (executionResult.error.stackTrace) {
|
||||
console.log('');
|
||||
console.log(chalk.gray('Stack trace:'));
|
||||
console.log(chalk.gray(executionResult.error.stackTrace));
|
||||
}
|
||||
}
|
||||
|
||||
if (executionResult.logs) {
|
||||
console.log('');
|
||||
console.log(chalk.bold('Logs:'));
|
||||
console.log(chalk.gray(executionResult.logs));
|
||||
}
|
||||
|
||||
@@ -59,9 +59,7 @@ export class LogicFunctionLogsCommand {
|
||||
: 'functions';
|
||||
|
||||
console.log(
|
||||
chalk.blue(`🚀 Watching ${appPath} ${functionIdentifier} logs:`),
|
||||
chalk.blue(`🚀 Watching ${appPath} ${functionIdentifier} logs:\n`),
|
||||
);
|
||||
|
||||
console.log('');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,7 @@ export class AppPublishCommand {
|
||||
await checkSdkVersionCompatibility(appPath);
|
||||
|
||||
console.log(chalk.blue('Publishing to npm...'));
|
||||
console.log(chalk.gray(`App path: ${appPath}`));
|
||||
console.log('');
|
||||
console.log(chalk.gray(`App path: ${appPath}\n`));
|
||||
|
||||
const result = await appPublish({
|
||||
appPath,
|
||||
|
||||
@@ -70,6 +70,7 @@ export const registerRemoteCommands = (program: Command): void => {
|
||||
.description('Add a new remote or re-authenticate an existing one')
|
||||
.option('--as <name>', 'Name for this remote')
|
||||
.option('--local', 'Connect to local development server')
|
||||
.option('--port <port>', 'Port for local server (use with --local)')
|
||||
.option('--token <token>', 'API key for non-interactive auth')
|
||||
.option('--url <url>', 'Server URL (alternative to positional arg)')
|
||||
.action(
|
||||
@@ -78,6 +79,7 @@ export const registerRemoteCommands = (program: Command): void => {
|
||||
options: {
|
||||
as?: string;
|
||||
local?: boolean;
|
||||
port?: string;
|
||||
token?: string;
|
||||
url?: string;
|
||||
},
|
||||
@@ -87,7 +89,12 @@ export const registerRemoteCommands = (program: Command): void => {
|
||||
|
||||
if (options.local) {
|
||||
const remoteName = options.as ?? 'local';
|
||||
const localUrl = await detectLocalServer();
|
||||
const preferredPort = options.port
|
||||
? parseInt(options.port, 10)
|
||||
: undefined;
|
||||
const localUrl = preferredPort
|
||||
? `http://localhost:${preferredPort}`
|
||||
: await detectLocalServer();
|
||||
|
||||
if (!localUrl) {
|
||||
console.error(
|
||||
@@ -102,7 +109,6 @@ export const registerRemoteCommands = (program: Command): void => {
|
||||
console.log(chalk.gray(`Found server at ${localUrl}`));
|
||||
ConfigService.setActiveRemote(remoteName);
|
||||
await authenticate(localUrl, options.token);
|
||||
console.log(chalk.green(`✓ Authenticated remote "${remoteName}".`));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -116,7 +122,6 @@ export const registerRemoteCommands = (program: Command): void => {
|
||||
|
||||
ConfigService.setActiveRemote(nameOrUrl);
|
||||
await authenticate(config.apiUrl, options.token);
|
||||
console.log(chalk.green(`✓ Re-authenticated remote "${nameOrUrl}".`));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -156,8 +161,6 @@ export const registerRemoteCommands = (program: Command): void => {
|
||||
if (defaultRemote === 'local') {
|
||||
await configService.setDefaultRemote(name);
|
||||
}
|
||||
|
||||
console.log(chalk.green(`✓ Authenticated remote "${name}".`));
|
||||
},
|
||||
);
|
||||
|
||||
@@ -196,8 +199,8 @@ export const registerRemoteCommands = (program: Command): void => {
|
||||
);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log(
|
||||
'\n',
|
||||
chalk.gray("Use 'twenty remote switch <name>' to change default"),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ConfigService } from '@/cli/utilities/config/config-service';
|
||||
import { checkServerHealth } from '@/cli/utilities/server/detect-local-server';
|
||||
import chalk from 'chalk';
|
||||
import type { Command } from 'commander';
|
||||
@@ -45,6 +46,20 @@ const containerExists = (): boolean => {
|
||||
}
|
||||
};
|
||||
|
||||
const checkDockerRunning = (): boolean => {
|
||||
try {
|
||||
execSync('docker info', { stdio: 'ignore' });
|
||||
|
||||
return true;
|
||||
} catch {
|
||||
console.error(
|
||||
chalk.red('Docker is not running. Please start Docker and try again.'),
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const validatePort = (value: string): number => {
|
||||
const port = parseInt(value, 10);
|
||||
|
||||
@@ -69,6 +84,12 @@ export const registerServerCommands = (program: Command): void => {
|
||||
let port = validatePort(options.port);
|
||||
|
||||
if (await checkServerHealth(port)) {
|
||||
const localUrl = `http://localhost:${port}`;
|
||||
const configService = new ConfigService();
|
||||
|
||||
ConfigService.setActiveRemote('local');
|
||||
await configService.setConfig({ apiUrl: localUrl });
|
||||
|
||||
console.log(
|
||||
chalk.green(`Twenty server is already running on localhost:${port}.`),
|
||||
);
|
||||
@@ -76,6 +97,10 @@ export const registerServerCommands = (program: Command): void => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkDockerRunning()) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (isContainerRunning()) {
|
||||
console.log(chalk.gray('Container is running but not healthy yet.'));
|
||||
|
||||
@@ -93,30 +118,13 @@ export const registerServerCommands = (program: Command): void => {
|
||||
);
|
||||
}
|
||||
|
||||
port = existingPort;
|
||||
|
||||
console.log(chalk.gray('Starting existing container...'));
|
||||
execSync(`docker start ${CONTAINER_NAME}`, { stdio: 'ignore' });
|
||||
port = existingPort;
|
||||
} else {
|
||||
try {
|
||||
execSync('docker info', { stdio: 'ignore' });
|
||||
} catch {
|
||||
console.error(
|
||||
chalk.red(
|
||||
'Docker is not running. Please start Docker and try again.',
|
||||
),
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(chalk.gray(`Pulling ${IMAGE}...`));
|
||||
|
||||
try {
|
||||
execSync(`docker pull ${IMAGE}`, { stdio: 'inherit' });
|
||||
} catch {
|
||||
console.log(chalk.gray('Pull failed, trying local image...'));
|
||||
}
|
||||
|
||||
console.log(chalk.gray('Starting Twenty container...'));
|
||||
|
||||
const runResult = spawnSync(
|
||||
'docker',
|
||||
[
|
||||
@@ -136,17 +144,18 @@ export const registerServerCommands = (program: Command): void => {
|
||||
);
|
||||
|
||||
if (runResult.status !== 0) {
|
||||
console.error(chalk.red('Failed to start Twenty container.'));
|
||||
console.error(chalk.red('\nFailed to start Twenty container.'));
|
||||
process.exit(runResult.status ?? 1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
chalk.green(`Twenty server starting on http://localhost:${port}`),
|
||||
);
|
||||
console.log(
|
||||
chalk.gray('Run `yarn twenty server logs` to follow startup progress.'),
|
||||
);
|
||||
const localUrl = `http://localhost:${port}`;
|
||||
const configService = new ConfigService();
|
||||
|
||||
ConfigService.setActiveRemote('local');
|
||||
await configService.setConfig({ apiUrl: localUrl });
|
||||
|
||||
console.log(chalk.green(`\nLocal remote configured → ${localUrl}`));
|
||||
});
|
||||
|
||||
server
|
||||
|
||||
@@ -18,8 +18,7 @@ export class AppTypecheckCommand {
|
||||
const appPath = options.appPath ?? CURRENT_EXECUTION_DIRECTORY;
|
||||
|
||||
console.log(chalk.blue('Running type check...'));
|
||||
console.log(chalk.gray(`App path: ${appPath}`));
|
||||
console.log('');
|
||||
console.log(chalk.gray(`App path: ${appPath}\n`));
|
||||
|
||||
const errors = await runTypecheck(appPath);
|
||||
|
||||
@@ -32,8 +31,8 @@ export class AppTypecheckCommand {
|
||||
console.log(formatTypecheckError(error));
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log(
|
||||
'\n',
|
||||
chalk.red(
|
||||
`✗ Found ${errors.length} type error${errors.length === 1 ? '' : 's'}`,
|
||||
),
|
||||
|
||||
@@ -13,8 +13,7 @@ export class AppUninstallCommand {
|
||||
askForConfirmation: boolean;
|
||||
}): Promise<ApiResponse<any>> {
|
||||
console.log(chalk.blue('🚀 Uninstall Twenty Application'));
|
||||
console.log(chalk.gray(`📁 App Path: ${appPath}`));
|
||||
console.log('');
|
||||
console.log(chalk.gray(`📁 App Path: ${appPath}\n`));
|
||||
|
||||
if (askForConfirmation && !(await this.confirmationPrompt())) {
|
||||
console.error(chalk.red('⛔️ Aborting uninstall'));
|
||||
|
||||
Reference in New Issue
Block a user