UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

177 lines • 7.47 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils"); const constants_1 = require("../constants"); const LintService_1 = __importDefault(require("../services/LintService")); class AbstractWriter { templates; ui; linter; upgradeMode; fileDescriptions = []; shouldConfirmBeforeWriting = true; firstFileWriteMessage; hasShownFirstWriteMessage = false; settings; isLintEnabled = true; constructor(options) { const { templates, term, upgradeMode, fileDescriptions, linter, settings, } = options; this.templates = templates; this.ui = term; this.upgradeMode = upgradeMode; this.fileDescriptions = fileDescriptions; this.linter = linter; this.settings = settings; } async lint(file) { const shouldLint = !LintService_1.default.shouldIgnorePattern(file); if (this.isLintEnabled && shouldLint) { await this.linter?.fix(file).catch(() => { }); } } async writeDirectoryTemplate(options) { const { context, destinationDir, filesToWrite, filesToSkip, shouldConfirmBeforeWriting = true, firstFileWriteMessage, } = options; this.shouldConfirmBeforeWriting = shouldConfirmBeforeWriting; this.firstFileWriteMessage = firstFileWriteMessage; this.hasShownFirstWriteMessage = false; const files = await this.templates.directoryTemplate({ kind: options.code, context: context ?? {}, }); let results = []; for (const generated of files) { const shouldWrite = !filesToWrite || filesToWrite.indexOf(generated.filename) > -1; const shouldSkip = filesToSkip && filesToSkip.indexOf(generated.filename) > -1; if (shouldWrite && !shouldSkip) { results = await this.writeFileIfChangedMixinResults(path_1.default.join(destinationDir, generated.relativePath), generated.contents, '', results, destinationDir); } } return results; } async writeFileIfChangedMixinResults(destination, contents, description, results, cwd = '') { const myResults = results ?? []; let desc = description; const name = path_1.default.basename(destination); let action = 'skipped'; if (spruce_skill_utils_1.diskUtil.isDir(destination)) { throw new Error(`Can't write to a directory ${destination}.`); } const fileDescription = this.getFileDescription(destination); if (!spruce_skill_utils_1.diskUtil.doesFileExist(destination)) { let write = true; if (this.shouldConfirmBeforeWriting && fileDescription?.confirmPromptOnFirstWrite) { this.ui.stopLoading(); write = await this.ui.confirm(fileDescription.confirmPromptOnFirstWrite); } if (write) { spruce_skill_utils_1.diskUtil.writeFile(destination, contents); action = 'generated'; } } else if (this.isFileDifferent(destination, contents) && this.shouldOverwriteIfChanged(destination)) { const cleanedName = this.cleanFilename(destination, cwd); const settings = { skipped: [], ...this.settings.get('writer') }; const isAlwaysSkipped = settings.skipped.indexOf(cleanedName) > -1; let write = !isAlwaysSkipped; if (!isAlwaysSkipped && this.shouldAskForOverwrite()) { if (!this.hasShownFirstWriteMessage && this.firstFileWriteMessage) { this.hasShownFirstWriteMessage = true; this.ui.renderLine(this.firstFileWriteMessage); this.ui.renderLine(''); } const answer = await this.ui.prompt({ type: 'select', label: `${cleanedName}`, options: { choices: [ { value: constants_1.FILE_ACTION_OVERWRITE, label: 'Overwrite', }, { value: constants_1.FILE_ACTION_SKIP, label: 'Skip', }, { value: constants_1.FILE_ACTION_ALWAYS_SKIP, label: 'Always skip', }, ], }, }); if (answer === constants_1.FILE_ACTION_ALWAYS_SKIP) { settings.skipped.push(cleanedName); this.settings.set('writer', settings); } write = answer === constants_1.FILE_ACTION_OVERWRITE; } if (write) { spruce_skill_utils_1.diskUtil.writeFile(destination, contents); action = 'updated'; } } if (!desc) { desc = fileDescription?.description; } if (!desc) { throw new Error(`No FileDescription provided for ${destination.replace(cwd, '')}. Check your feature's fileDescriptions property.`); } myResults.push({ name, description: desc, path: destination, action }); await this.lint(destination); return myResults; } isFileDifferent(destination, contents) { return spruce_skill_utils_1.diskUtil.isFileDifferent(destination, contents); } cleanFilename(destination, cwd) { let relativeFile = destination.replace(cwd, ''); if (relativeFile[0] === path_1.default.sep) { relativeFile = relativeFile.substr(1); } return relativeFile; } shouldOverwriteIfChanged(destination) { if (!this.upgradeMode) { return true; } if (this.upgradeMode === 'forceEverything') { return true; } let description = this.getFileDescription(destination); return description?.shouldOverwriteWhenChanged ?? false; } getFileDescription(destination) { const lower = destination.toLowerCase(); for (const d of this.fileDescriptions ?? []) { if (lower.search(d.path.toLowerCase()) > -1) { return d; } } return undefined; } shouldAskForOverwrite() { if (this.shouldConfirmBeforeWriting && this.upgradeMode === 'askForChanged') { return true; } return false; } resolveFilenameWithFallback(dirOrFile, fallbackFileName) { const isDir = spruce_skill_utils_1.diskUtil.doesDirExist(dirOrFile) && fs_1.default.lstatSync(dirOrFile).isDirectory() && path_1.default.extname(dirOrFile).length === 0; return isDir ? spruce_skill_utils_1.diskUtil.resolvePath(dirOrFile, fallbackFileName) : dirOrFile; } } exports.default = AbstractWriter; //# sourceMappingURL=AbstractWriter.js.map