UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

128 lines (109 loc) 3.97 kB
import { SpruceSchemas } from '#spruce/schemas/schemas.types' import bootSkillOptionsSchema from '#spruce/schemas/spruceCli/v2020_07_22/bootSkillOptions.schema' import SpruceError from '../../../errors/SpruceError' import CommandServiceImpl from '../../../services/CommandService' import AbstractAction from '../../AbstractAction' import { FeatureActionResponse } from '../../features.types' export default class BootAction extends AbstractAction<OptionsSchema> { public optionsSchema: OptionsSchema = bootSkillOptionsSchema public commandAliases = ['boot'] public invocationMessage = 'Booting skill... ⚡️' private onDataHandler: ((msg: string) => void) | null | undefined private onErrorHandler: ((msg: string) => void) | null | undefined public async execute(options: Options): Promise<FeatureActionResponse> { const command = this.Service('command') let script = 'boot' this.onDataHandler = options.onData this.onErrorHandler = options.onError if (options.local) { script += '.local' } let runningPromise: any let bootPromise = new Promise((resolve, reject) => { runningPromise = this.boot(command, script, resolve, reject) }) const hints = ['Skill booted succesfully!', 'Skill torn down cleanly!'] const meta = { isBooted: false, kill: command.kill.bind(command), pid: command.pid() as number, promise: runningPromise, bootPromise, } return new Promise((resolve, reject) => { bootPromise = bootPromise .then(() => { meta.isBooted = true return { meta, hints } }) .catch((err) => { reject(err) return err }) if (!options.shouldReturnImmediately) { void bootPromise.then(() => resolve({ meta, hints })) } else { meta.bootPromise = bootPromise resolve({ meta, hints, }) } }) } private async boot( command: CommandServiceImpl, script: string, resolve: (value: unknown) => void, reject: (reason?: any) => void ) { let isBooted = false try { const results = await command.execute(`yarn ${script}`, { onData: (data) => { this.onDataHandler?.(data) if (!isBooted && data.search(':: Skill booted') > -1) { isBooted = true resolve(undefined) } }, onError: (data) => { this.onErrorHandler?.(data) }, }) if (!isBooted) { isBooted = true resolve(undefined) } return results } catch (err: any) { let mappedErr = err if ( mappedErr.message.search( /Error: cannot find module.*?build\/index/gi ) > -1 ) { mappedErr = new SpruceError({ code: 'BOOT_ERROR', friendlyMessage: 'You must build your skill before you can boot it!', }) } if (!isBooted) { reject(mappedErr) } else { throw mappedErr } } return null } } type OptionsSchema = SpruceSchemas.SpruceCli.v2020_07_22.BootSkillOptionsSchema type Options = SpruceSchemas.SpruceCli.v2020_07_22.BootSkillOptions export interface BootMeta { kill: () => void pid: number promise: Promise<void> isBooted: boolean bootPromise: Promise<void> }