Fixing bug where templates may get mapped before loaded from their files (#10111)

* Fixing potential bad order of template loading and map construction

* Fixing bug where templates get mapped before loaded from file

* Parallelizing loading templates from file
This commit is contained in:
Benjin Dubishar
2020-04-22 17:01:19 -07:00
committed by GitHub
parent 8311c3985d
commit 52f33cc587
7 changed files with 134 additions and 64 deletions

View File

@@ -1,43 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as constants from '../common/constants';
import * as templates from './templates';
export class ProjectScriptType {
type: string;
friendlyName: string;
templateScript: string;
constructor(type: string, friendlyName: string, templateScript: string) {
this.type = type;
this.friendlyName = friendlyName;
this.templateScript = templateScript;
}
}
export const script: string = 'script';
export const table: string = 'table';
export const view: string = 'view';
export const storedProcedure: string = 'storedProcedure';
export const folder: string = 'folder';
export const projectScriptTypes: ProjectScriptType[] = [
new ProjectScriptType(script, constants.scriptFriendlyName, templates.newSqlScriptTemplate),
new ProjectScriptType(table, constants.tableFriendlyName, templates.newSqlTableTemplate),
new ProjectScriptType(view, constants.viewFriendlyName, templates.newSqlViewTemplate),
new ProjectScriptType(storedProcedure, constants.storedProcedureFriendlyName, templates.newSqlStoredProcedureTemplate),
];
export const projectScriptTypeMap: Record<string, ProjectScriptType> = {};
for (const scriptType of projectScriptTypes) {
if (Object.keys(projectScriptTypeMap).find(s => s === scriptType.type.toLocaleLowerCase() || s === scriptType.friendlyName.toLocaleLowerCase())) {
throw new Error(`Script type map already contains ${scriptType.type} or its friendlyName.`);
}
projectScriptTypeMap[scriptType.type.toLocaleLowerCase()] = scriptType;
projectScriptTypeMap[scriptType.friendlyName.toLocaleLowerCase()] = scriptType;
}

View File

@@ -4,27 +4,85 @@
*--------------------------------------------------------------------------------------------*/
import * as path from 'path';
import * as constants from '../common/constants';
import { promises as fs } from 'fs';
// Project templates
export let newSqlProjectTemplate: string;
// Script templates
// Object types
export let newSqlScriptTemplate: string;
export let newSqlTableTemplate: string;
export let newSqlViewTemplate: string;
export let newSqlStoredProcedureTemplate: string;
export const script: string = 'script';
export const table: string = 'table';
export const view: string = 'view';
export const storedProcedure: string = 'storedProcedure';
export const folder: string = 'folder';
// Object maps
let scriptTypeMap: Record<string, ProjectScriptType> = {};
export function projectScriptTypeMap(): Record<string, ProjectScriptType> {
if (Object.keys(scriptTypeMap).length === 0) {
throw new Error('Templates must be loaded from file before attempting to use.');
}
return scriptTypeMap;
}
let scriptTypes: ProjectScriptType[] = [];
export function projectScriptTypes(): ProjectScriptType[] {
if (scriptTypes.length === 0) {
throw new Error('Templates must be loaded from file before attempting to use.');
}
return scriptTypes;
}
export async function loadTemplates(templateFolderPath: string) {
newSqlProjectTemplate = await loadTemplate(templateFolderPath, 'newSqlProjectTemplate.xml');
await Promise.all([
Promise.resolve(newSqlProjectTemplate = await loadTemplate(templateFolderPath, 'newSqlProjectTemplate.xml')),
loadObjectTypeInfo(script, constants.scriptFriendlyName, templateFolderPath, 'newTsqlScriptTemplate.sql'),
loadObjectTypeInfo(table, constants.tableFriendlyName, templateFolderPath, 'newTsqlTableTemplate.sql'),
loadObjectTypeInfo(view, constants.viewFriendlyName, templateFolderPath, 'newTsqlViewTemplate.sql'),
loadObjectTypeInfo(storedProcedure, constants.storedProcedureFriendlyName, templateFolderPath, 'newTsqlStoredProcedureTemplate.sql')
]);
newSqlScriptTemplate = await loadTemplate(templateFolderPath, 'newTsqlScriptTemplate.sql');
newSqlTableTemplate = await loadTemplate(templateFolderPath, 'newTsqlTableTemplate.sql');
newSqlViewTemplate = await loadTemplate(templateFolderPath, 'newTsqlViewTemplate.sql');
newSqlStoredProcedureTemplate = await loadTemplate(templateFolderPath, 'newTsqlStoredProcedureTemplate.sql');
for (const scriptType of scriptTypes) {
if (Object.keys(projectScriptTypeMap).find(s => s === scriptType.type.toLocaleLowerCase() || s === scriptType.friendlyName.toLocaleLowerCase())) {
throw new Error(`Script type map already contains ${scriptType.type} or its friendlyName.`);
}
scriptTypeMap[scriptType.type.toLocaleLowerCase()] = scriptType;
scriptTypeMap[scriptType.friendlyName.toLocaleLowerCase()] = scriptType;
}
}
async function loadObjectTypeInfo(key: string, friendlyName: string, templateFolderPath: string, fileName: string) {
const template = await loadTemplate(templateFolderPath, fileName);
scriptTypes.push(new ProjectScriptType(key, friendlyName, template));
}
async function loadTemplate(templateFolderPath: string, fileName: string): Promise<string> {
return (await fs.readFile(path.join(templateFolderPath, fileName))).toString();
}
export class ProjectScriptType {
type: string;
friendlyName: string;
templateScript: string;
constructor(type: string, friendlyName: string, templateScript: string) {
this.type = type;
this.friendlyName = friendlyName;
this.templateScript = templateScript;
}
}
/**
* For testing purposes only
*/
export function reset() {
scriptTypeMap = {};
scriptTypes = [];
}