import * as fs from 'fs' ; import * as path from 'path' ; import * as yeoman from 'yeoman-environment' ; import { nls } from '../i18n' ; import { ForceGeneratorAdapter } from '../utils' ; import { CreateOutput , TemplateOptions , TemplateType } from '../utils/types' ; import { loadCustomTemplatesGitRepo } from './gitRepoUtils' ; interface FsError extends Error { code : string ; } /**
 * Template Service
 */ export class TemplateService { private static instance : TemplateService ; private adapter : ForceGeneratorAdapter ; private env : yeoman ; constructor ( cwd = process . cwd ( ) ) { this . adapter = new ForceGeneratorAdapter ( ) ; this . env = yeoman . createEnv ( undefined , { cwd } , this . adapter ) ; } param cwd public static getInstance ( cwd ? ) { if ( ! TemplateService . instance ) { TemplateService . instance = new TemplateService ( cwd ) ; } else if ( cwd ) { TemplateService . instance . cwd = cwd ; } return TemplateService . instance ; } /**
     * Getting cwd of current yeoman environment
     */ public get cwd ( ) { return this . env . cwd ; } /**
     * Setting cwd of current yeoman environment
     * In VS Code, it's typically the root workspace path
     */ public set cwd ( cwd ) { this . env . cwd = cwd ; } /**
     * Look up package version of @salesforce/templates package to supply a default API version
     */ public static getDefaultApiVersion ( ) { const packageJsonPath = path . join ( '..' , '..' , 'package.json' ) ; const versionTrimmed = require ( packageJsonPath ) . version . trim ( ) ; return `${ versionTrimmed . split ( '.' ) [ 0 ] }.0` ; } param templateType param templateOptions param customTemplatesRootPathOrGitRepo public async create < TOptions extends TemplateOptions > ( templateType , templateOptions , customTemplatesRootPathOrGitRepo ? ) { await this . setCustomTemplatesRootPathOrGitRepo ( customTemplatesRootPathOrGitRepo ) ; if ( customTemplatesRootPathOrGitRepo ) { this . resetEnv ( ) ; } const generatorClass = TemplateType [ templateType ] . toString ( ) . charAt ( 0 ) . toLowerCase ( ) + TemplateType [ templateType ] . toString ( ) . slice ( 1 ) + 'Generator' ; const generatorNamespace = `@salesforce/${ generatorClass }` ; let generator = this . env . get ( generatorNamespace ) ; if ( ! generator ) { generator = ( await import ( `../generators/${ generatorClass }` ) ) . default ; const generatorPackagePath = path . join ( __dirname , '..' , '..' ) ; this . env . registerStub ( generator ! , generatorNamespace , generatorPackagePath ) ; } this . adapter . log . clear ( ) ; return new Promise ( ( resolve , reject ) => { this . env . run ( generatorNamespace , templateOptions , err => { if ( err ) { reject ( err ) ; } const outputDir = path . resolve ( this . cwd , templateOptions . outputdir ! ) ; const created = this . adapter . log . getCleanOutput ( ) ; const rawOutput = nls . localize ( 'RawOutput' , [ outputDir , this . adapter . log . getOutput ( ) ] ) ; const result = { outputDir , created , rawOutput } ; resolve ( result ) ; } ) ; } ) ; } /**
     * Local custom templates path set by user
     * or set to a local cache of a git repo.
     * Used by the generators.
     */ public customTemplatesRootPath ? : string ; private resetEnv ( ) { const cwd = this . env . cwd ; this . env = yeoman . createEnv ( undefined , { cwd } , this . adapter ) ; } param customTemplatesRootPathOrGitRepo param forceLoadingRemoteRepo public async setCustomTemplatesRootPathOrGitRepo ( pathOrRepoUri ? , forceLoadingRemoteRepo = false ) { if ( pathOrRepoUri === undefined ) { this . customTemplatesRootPath = undefined ; return ; } try { const url = new URL ( pathOrRepoUri ) ; if ( url ) { this . customTemplatesRootPath = await loadCustomTemplatesGitRepo ( url , forceLoadingRemoteRepo ) ; } } catch ( error ) { const err = error as FsError ; if ( err . code !== 'ERR_INVALID_URL' ) { throw error ; } const localTemplatesPath = pathOrRepoUri ; if ( fs . existsSync ( localTemplatesPath ) ) { this . customTemplatesRootPath = localTemplatesPath ; } else { throw new Error ( nls . localize ( 'localCustomTemplateDoNotExist' , localTemplatesPath ) ) ; } } } }