UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

155 lines (131 loc) 4.72 kB
import { diskUtil } from '@sprucelabs/spruce-skill-utils' import { ErrorTemplateItem } from '@sprucelabs/spruce-templates' import { GeneratedFile } from '../../../types/cli.types' import AbstractWriter, { WriteResults } from '../../../writers/AbstractWriter' export default class ErrorWriter extends AbstractWriter { public async writeOrAppendErrorsToClass( destinationDir: string, errors: ErrorTemplateItem[] ): Promise<WriteResults> { let results: WriteResults = [] if (errors.length === 0) { // todo move to proper error throw new Error('Need at least one error') } const resolvedDestination = diskUtil.resolvePath( destinationDir, `SpruceError.ts` ) if (!diskUtil.doesFileExist(resolvedDestination)) { this.ui.startLoading('Creating Error class') const errorContents = this.templates.error({ errors: errors.filter((error) => !error.isNested), }) results = await this.writeFileIfChangedMixinResults( resolvedDestination, errorContents, 'A new subclass of SpruceBaseError where you can control your error messaging.', results ) } else { this.ui.startLoading('Updating Error class') const updates = await this.dropInNewErrorCases( errors, resolvedDestination ) if (updates.length > 0) { results.push({ ...updates[0], description: `${updates.length} new error cases were dropped in.`, }) } } return results } private async dropInNewErrorCases( errors: ErrorTemplateItem[], destinationFile: string ) { let results: GeneratedFile[] = [] for (const error of errors) { if (!error.isNested) { const dropInResults = await this.dropInErrorCaseIfMissing( error, destinationFile ) results.push(...dropInResults) } } return results } private async dropInErrorCaseIfMissing( error: ErrorTemplateItem, destinationFile: string ) { let results: GeneratedFile[] = [] const errorBlock = this.templates.error({ errors: [error], renderClassDefinition: false, }) // Try and drop in the block right before "default:" const currentErrorContents = diskUtil.readFile(destinationFile) const blockMatches = currentErrorContents.search(/default:/g) if ( blockMatches > -1 && !this.doesErrorCaseExist(currentErrorContents, error) ) { const newErrorContents = currentErrorContents.substring(0, blockMatches) + '\n' + errorBlock + '\n' + currentErrorContents.substring(blockMatches) results = await this.writeFileIfChangedMixinResults( destinationFile, newErrorContents, `A new block was added to handle ${error.code}.`, results ) } return results } private doesErrorCaseExist( currentContents: string, error: ErrorTemplateItem ) { return currentContents.search(new RegExp(`case '${error.code}':`)) > -1 } public async writeOptionsTypesFile( destinationDir: string, errorTemplateItems: ErrorTemplateItem[] ): Promise<WriteResults> { const contents = this.templates.errorOptionsTypes({ options: errorTemplateItems, }) const destination = diskUtil.resolvePath( destinationDir, 'options.types.ts' ) this.ui.startLoading('Updating error options...') const results = this.writeFileIfChangedMixinResults( destination, contents, 'A union of all possible error codes and their options.' ) return results } public async writePlugin(cwd: string) { const destination = diskUtil.resolveHashSprucePath( cwd, 'features', 'error.plugin.ts' ) const pluginContents = this.templates.errorPlugin() const results = this.writeFileIfChangedMixinResults( destination, pluginContents, 'Supports your skill with Error generation and handling.' ) return results } }