import { readdirSync } from 'fs' ; import { normalize , resolve } from 'path' ; import { isDirectory } from '../utils/fs' ; import { ITemplate , ITemplateTable } from './types' ; import Template from './Template' ; let duplicateTemplateNameOrder = 0 ; export default class TemplateTable implements ITemplateTable { public static getInstance ( templatesPath ) { if ( ! this . _instance ) { this . _instance = new TemplateTable ( templatesPath ) ; } return this . _instance ; } public static freeInstance ( ) { this . _instance = null ; } public async init ( ) { try { const templatesPath = this . _templatesPath ; const templateDirs = readdirSync ( templatesPath ) . map ( ( dir ) => normalize ( resolve ( templatesPath , dir ) ) ) . filter ( ( dir ) => isDirectory ( dir ) ) ; await Promise . all ( templateDirs . map ( async ( templateDir ) => { const template = await Template . createTemplate ( templateDir ) ; if ( template ) { this . add ( template ) ; } } ) ) ; } catch ( e ) { TemplateTable . freeInstance ( ) ; throw e ; } } public getById ( templateId ) { return this . _idTemplateTable . get ( templateId ) ; } public getByName ( templateName ) { return this . getById ( this . _nameIdTable . get ( templateName ) || '' ) ; } /**
     * Add a template into the template table.
     * If the template table already has the same template, cover it with the new one.
     */ public add ( template ) { const existingTemplateId = this . _nameIdTable . get ( template . name ) ; if ( existingTemplateId && existingTemplateId !== template . id ) { template . name = `${ template . name }.${ duplicateTemplateNameOrder += 1 }` ; } this . _idTemplateTable . set ( template . id , template ) ; this . _nameIdTable . set ( template . name , template . id ) ; } public deleteById ( templateId ) { const templateToDelete = this . getById ( templateId ) ; this . delete ( templateToDelete ) ; } public deleteByName ( templateName ) { const templateToDelete = this . getByName ( templateName ) ; this . delete ( templateToDelete ) ; } public entries ( ) { return Array . from ( this . _idTemplateTable . values ( ) ) ; } public size ( ) { return this . _idTemplateTable . size ; } private constructor ( templatesPath ) { this . _templatesPath = templatesPath ; } private delete ( template ) { if ( template ) { this . _nameIdTable . delete ( template . name ) ; this . _idTemplateTable . delete ( template . id ) ; } } private static _instance : TemplateTable | null = null ; private _idTemplateTable = new Map < string , ITemplate > ( ) ; private _nameIdTable = new Map < string , string > ( ) ; private _templatesPath : string ; }