@launchql/cli
Version:
LaunchQL CLI
134 lines (128 loc) • 4.75 kB
JavaScript
import { LaunchQLPackage } from '@launchql/core';
import { Logger } from '@launchql/logger';
import { errors } from '@launchql/types';
import { extractFirst } from '../utils/argv';
import { selectPackage } from '../utils/module-utils';
import * as path from 'path';
const log = new Logger('tag');
const tagUsageText = `
LaunchQL Tag Command:
lql tag [tag_name] [OPTIONS]
Add tags to changes for versioning.
Arguments:
tag_name Name of the tag to create
Options:
--help, -h Show this help message
--package <name> Target specific package
--changeName <name> Target specific change (default: latest)
--comment <text> Optional tag comment
--cwd <directory> Working directory (default: current directory)
Examples:
lql tag v1.0.0 Add tag to latest change
lql tag v1.0.0 --comment "Initial release" Add tag with comment
lql tag v1.1.0 --package mypackage --changeName my-change Tag specific change in package
`;
export default async (argv, prompter, _options) => {
// Show usage if explicitly requested
if (argv.help || argv.h) {
console.log(tagUsageText);
process.exit(0);
}
const { first: tagName, newArgv } = extractFirst(argv);
const cwdResult = await prompter.prompt(newArgv, [
{
type: 'text',
name: 'cwd',
message: 'Working directory',
required: false,
default: process.cwd(),
useDefault: true
}
]);
const cwd = cwdResult.cwd || process.cwd();
const pkg = new LaunchQLPackage(cwd);
let packageName;
if (argv.package) {
packageName = argv.package;
log.info(`Using specified package: ${packageName}`);
}
else if (pkg.isInModule()) {
packageName = pkg.getModuleName();
log.info(`Using current module: ${packageName}`);
}
else if (pkg.isInWorkspace()) {
packageName = await selectPackage(newArgv, prompter, cwd, 'add tag to', log);
if (!packageName) {
throw new Error('No package selected. Cannot add tag without specifying a target package.');
}
}
else {
throw new Error('This command must be run inside a LaunchQL workspace or module.');
}
const questions = [];
if (!tagName) {
questions.push({
type: 'text',
name: 'tagName',
message: 'Tag name',
required: true,
validate: (value) => {
if (!value || value.trim().length === 0) {
return false;
}
if (value.includes('/')) {
return false;
}
if (value.includes('@')) {
return false;
}
return true;
}
});
}
questions.push({
type: 'text',
name: 'changeName',
message: 'Target change name (leave empty for latest change)',
required: false
}, {
type: 'text',
name: 'comment',
message: 'Tag comment (optional)',
required: false
});
const answers = await prompter.prompt(newArgv, questions);
const finalTagName = tagName || answers.tagName;
const changeName = answers.changeName;
const comment = answers.comment;
try {
if (argv.package || !pkg.isInModule()) {
const moduleMap = pkg.getModuleMap();
const module = moduleMap[packageName];
if (!module) {
throw errors.MODULE_NOT_FOUND({ name: packageName });
}
const workspacePath = pkg.getWorkspacePath();
const absoluteModulePath = path.resolve(workspacePath, module.path);
const originalCwd = process.cwd();
process.chdir(absoluteModulePath);
try {
const modulePkg = new LaunchQLPackage(absoluteModulePath);
modulePkg.addTag(finalTagName.trim(), changeName?.trim() || undefined, comment?.trim() || undefined);
log.info(`Successfully added tag '${finalTagName}' to ${changeName || 'latest change'} in package '${packageName}'`);
}
finally {
process.chdir(originalCwd);
}
}
else {
pkg.addTag(finalTagName.trim(), changeName?.trim() || undefined, comment?.trim() || undefined);
log.info(`Successfully added tag '${finalTagName}' to ${changeName || 'latest change'}`);
}
}
catch (error) {
log.error(`Failed to add tag: ${error instanceof Error ? error.message : String(error)}`);
throw error;
}
return newArgv;
};