@diagramers/cli
Version:
Diagramers CLI - Command-line tools for managing Diagramers projects
196 lines • 8.52 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TemplateUpdater = void 0;
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const glob = __importStar(require("glob"));
const chalk_1 = __importDefault(require("chalk"));
const child_process_1 = require("child_process");
class TemplateUpdater {
constructor() {
this.currentProjectPath = process.cwd();
this.tempTemplatePath = path.join(this.currentProjectPath, '.temp-template');
}
async update(options) {
// Check if we're in a valid project directory
if (!await this.isValidProject()) {
throw new Error('Not a valid project directory. Please run this command from your project root.');
}
console.log(chalk_1.default.blue('🔄 Checking for template updates...'));
// Create backup if requested
if (options.backup) {
await this.createBackup();
}
try {
// Download latest template
await this.downloadTemplate(options.template || '@diagramers/api');
// Get list of files that can be updated
const updateableFiles = await this.getUpdateableFiles();
// Check for conflicts
const conflicts = await this.checkConflicts(updateableFiles);
if (conflicts.length > 0 && !options.force) {
console.log(chalk_1.default.yellow('⚠️ Conflicts detected in the following files:'));
conflicts.forEach(file => console.log(chalk_1.default.yellow(` - ${file}`)));
console.log(chalk_1.default.yellow('Use --force to overwrite these files'));
throw new Error('Update aborted due to conflicts');
}
// Perform the update
await this.performUpdate(updateableFiles, options.force);
console.log(chalk_1.default.green('✅ Project updated successfully!'));
console.log(chalk_1.default.yellow('📝 Review the changes and test your application'));
}
finally {
// Clean up temporary template
await this.cleanup();
}
}
async isValidProject() {
const packageJsonPath = path.join(this.currentProjectPath, 'package.json');
const mainTsPath = path.join(this.currentProjectPath, 'main.ts');
return await fs.pathExists(packageJsonPath) && await fs.pathExists(mainTsPath);
}
async createBackup() {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const backupPath = path.join(this.currentProjectPath, `backup-${timestamp}`);
// Create backup directory first
await fs.ensureDir(backupPath);
// Copy files individually to avoid the subdirectory issue
const filesToBackup = [
'src',
'main.ts',
'package.json',
'tsconfig.json',
'webpack.config.js',
'README.md',
'.gitignore'
];
for (const item of filesToBackup) {
const sourcePath = path.join(this.currentProjectPath, item);
const destPath = path.join(backupPath, item);
if (await fs.pathExists(sourcePath)) {
await fs.copy(sourcePath, destPath);
}
}
console.log(chalk_1.default.blue(`📦 Backup created at: ${backupPath}`));
}
async downloadTemplate(templatePackage) {
console.log(chalk_1.default.blue(`📦 Downloading latest template: ${templatePackage}`));
// Create temporary directory
await fs.ensureDir(this.tempTemplatePath);
// Only download from npm registry
await this.downloadFromNpm(templatePackage);
}
async downloadFromNpm(templatePackage) {
const npmCachePath = path.join(this.tempTemplatePath, 'node_modules', templatePackage);
try {
// Use npm pack to download the package
(0, child_process_1.execSync)(`npm pack ${templatePackage} --silent`, {
cwd: this.tempTemplatePath,
stdio: 'pipe'
});
// Find the downloaded tarball
const files = await fs.readdir(this.tempTemplatePath);
const tarball = files.find(file => file.endsWith('.tgz'));
if (!tarball) {
throw new Error('No tarball found after npm pack');
}
// Extract the tarball
(0, child_process_1.execSync)(`tar -xzf ${tarball} --strip-components=1`, {
cwd: this.tempTemplatePath,
stdio: 'pipe'
});
// Clean up tarball
await fs.remove(path.join(this.tempTemplatePath, tarball));
console.log(chalk_1.default.green(`✅ Template downloaded from npm: ${templatePackage}`));
}
catch (error) {
throw new Error(`Failed to download template from npm: ${error.message}`);
}
}
async getUpdateableFiles() {
const updateablePatterns = [
'src/helpers/**/*',
'src/config/**/*',
'src/server/**/*',
'webpack.config.js',
'tsconfig.json'
];
const files = [];
for (const pattern of updateablePatterns) {
const matches = glob.sync(pattern, { cwd: this.tempTemplatePath });
files.push(...matches);
}
return files;
}
async checkConflicts(files) {
const conflicts = [];
for (const file of files) {
const templatePath = path.join(this.tempTemplatePath, file);
const projectPath = path.join(this.currentProjectPath, file);
if (await fs.pathExists(templatePath) && await fs.pathExists(projectPath)) {
const templateContent = await fs.readFile(templatePath, 'utf8');
const projectContent = await fs.readFile(projectPath, 'utf8');
// Simple conflict detection - if files are different
if (templateContent !== projectContent) {
conflicts.push(file);
}
}
}
return conflicts;
}
async performUpdate(files, force = false) {
console.log(chalk_1.default.blue('📝 Updating project files...'));
for (const file of files) {
const templatePath = path.join(this.tempTemplatePath, file);
const projectPath = path.join(this.currentProjectPath, file);
if (await fs.pathExists(templatePath)) {
await fs.ensureDir(path.dirname(projectPath));
await fs.copy(templatePath, projectPath);
console.log(chalk_1.default.green(`✅ Updated: ${file}`));
}
}
}
async cleanup() {
if (await fs.pathExists(this.tempTemplatePath)) {
await fs.remove(this.tempTemplatePath);
}
}
}
exports.TemplateUpdater = TemplateUpdater;
//# sourceMappingURL=template-updater.js.map