This commit is contained in:
Eric Jizba 2019-02-15 16:24:33 -08:00 коммит произвёл GitHub
Родитель 7d708716e3
Коммит 03274e2bbe
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 264 добавлений и 29 удалений

Просмотреть файл

@ -6,8 +6,9 @@
import { parseError } from 'vscode-azureextensionui';
import { localize } from "./localize";
interface IFunctionJson {
export interface IFunctionJson {
disabled?: boolean;
scriptFile?: string;
bindings: IFunctionBinding[];
}

Просмотреть файл

@ -7,6 +7,7 @@ import * as fse from 'fs-extra';
import * as path from 'path';
import { IAzureUserInput } from 'vscode-azureextensionui';
import { ProjectLanguage } from '../../constants';
import { IFunctionJson } from '../../FunctionConfig';
import { localize } from "../../localize";
import { IScriptFunctionTemplate } from '../../templates/parseScriptTemplates';
import * as fsUtil from '../../utils/fs';
@ -42,8 +43,8 @@ export function getScriptFileNameFromLanguage(language: string): string | undefi
*/
export class ScriptFunctionCreator extends FunctionCreatorBase {
protected _template: IScriptFunctionTemplate;
protected _functionName: string;
private _language: string;
private _functionName: string;
constructor(functionAppPath: string, template: IScriptFunctionTemplate, language: string) {
super(functionAppPath, template);
@ -74,7 +75,13 @@ export class ScriptFunctionCreator extends FunctionCreatorBase {
for (const key of Object.keys(userSettings)) {
this._template.functionConfig.inBinding[key] = userSettings[key];
}
await fsUtil.writeFormattedJson(path.join(functionPath, 'function.json'), this._template.functionConfig.functionJson);
const functionJson: IFunctionJson = this._template.functionConfig.functionJson;
if (this.editFunctionJson) {
await this.editFunctionJson(functionJson);
}
await fsUtil.writeFormattedJson(path.join(functionPath, 'function.json'), functionJson);
const mainFileName: string | undefined = getScriptFileNameFromLanguage(this._language);
if (mainFileName) {
@ -84,6 +91,8 @@ export class ScriptFunctionCreator extends FunctionCreatorBase {
}
}
protected editFunctionJson?(functionJson: IFunctionJson): Promise<void>;
private validateTemplateName(name: string | undefined): string | undefined {
if (!name) {
return localize('azFunc.emptyTemplateNameError', 'The template name cannot be empty.');

Просмотреть файл

@ -0,0 +1,25 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as fse from 'fs-extra';
import * as path from 'path';
import { tsConfigFileName, tsDefaultOutDir } from '../../constants';
import { IFunctionJson } from '../../FunctionConfig';
import { ScriptFunctionCreator } from './ScriptFunctionCreator';
export class TypeScriptFunctionCreator extends ScriptFunctionCreator {
protected async editFunctionJson(functionJson: IFunctionJson): Promise<void> {
let outDir: string = tsDefaultOutDir;
try {
const tsconfigPath: string = path.join(this._functionAppPath, tsConfigFileName);
// tslint:disable-next-line:no-unsafe-any
outDir = (await fse.readJSON(tsconfigPath)).compilerOptions.outDir;
} catch {
// ignore and use default outDir
}
functionJson.scriptFile = path.join('..', outDir, this._functionName, 'index.js');
}
}

Просмотреть файл

@ -26,6 +26,7 @@ import { CSharpFunctionCreator } from './CSharpFunctionCreator';
import { FunctionCreatorBase } from './FunctionCreatorBase';
import { JavaFunctionCreator } from './JavaFunctionCreator';
import { ScriptFunctionCreator } from './ScriptFunctionCreator';
import { TypeScriptFunctionCreator } from './TypeScriptFunctionCreator';
async function promptForSetting(actionContext: IActionContext, localSettingsPath: string, setting: IFunctionSetting): Promise<string> {
if (setting.resourceType !== undefined) {
@ -68,7 +69,7 @@ async function promptForStringSetting(setting: IFunctionSetting): Promise<string
return await ext.ui.showInputBox(options);
}
// tslint:disable-next-line:max-func-body-length
// tslint:disable-next-line:max-func-body-length cyclomatic-complexity
export async function createFunction(
actionContext: IActionContext,
functionAppPath?: string,
@ -144,6 +145,9 @@ export async function createFunction(
case ProjectLanguage.CSharp:
functionCreator = new CSharpFunctionCreator(functionAppPath, template);
break;
case ProjectLanguage.TypeScript:
functionCreator = new TypeScriptFunctionCreator(functionAppPath, <IScriptFunctionTemplate>template, language);
break;
default:
functionCreator = new ScriptFunctionCreator(functionAppPath, <IScriptFunctionTemplate>template, language);
break;

Просмотреть файл

@ -4,38 +4,105 @@
*--------------------------------------------------------------------------------------------*/
import * as fse from 'fs-extra';
import * as os from 'os';
import * as path from 'path';
import { func, funcWatchProblemMatcher, gitignoreFileName, hostFileName, hostStartCommand, localSettingsFileName, ProjectRuntime, proxiesFileName, TemplateFilter } from '../../constants';
import { ILocalAppSettings } from '../../LocalAppSettings';
import { confirmOverwriteFile, writeFormattedJson } from "../../utils/fs";
import { ProjectCreatorBase } from './ProjectCreatorBase';
// https://github.com/github/gitignore/blob/master/Node.gitignore
// tslint:disable-next-line:no-multiline-string
const gitignore: string = `bin
const gitignore: string = `# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# Azure Functions artifacts
bin
obj
csx
.vs
edge
Publish
*.user
*.suo
*.cscfg
*.Cache
project.lock.json
/packages
/TestResults
/tools/NuGet.exe
/App_Data
/secrets
/data
.secrets
appsettings.json
local.settings.json
node_modules
# TypeScript output
dist
out
`;
/**
@ -47,6 +114,8 @@ export class ScriptProjectCreatorBase extends ProjectCreatorBase {
public readonly templateFilter: TemplateFilter = TemplateFilter.All;
public readonly functionsWorkerRuntime: string | undefined;
protected funcignore: string[] = ['.git*', '.vscode', 'local.settings.json', 'test'];
public getTasksJson(): {} {
return {
version: '2.0.0',
@ -101,6 +170,11 @@ export class ScriptProjectCreatorBase extends ProjectCreatorBase {
if (await confirmOverwriteFile(gitignorePath)) {
await fse.writeFile(gitignorePath, gitignore);
}
const funcIgnorePath: string = path.join(this.functionAppPath, '.funcignore');
if (await confirmOverwriteFile(funcIgnorePath)) {
await fse.writeFile(funcIgnorePath, this.funcignore.sort().join(os.EOL));
}
}
public async onInitProjectForVSCode(): Promise<void> {

Просмотреть файл

@ -0,0 +1,113 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from 'path';
import { IActionContext } from 'vscode-azureextensionui';
import { extInstallTaskName, func, funcWatchProblemMatcher, hostStartCommand, ProjectRuntime, tsConfigFileName, tsDefaultOutDir } from '../../constants';
import { confirmOverwriteFile, writeFormattedJson } from '../../utils/fs';
import { JavaScriptProjectCreator } from "./JavaScriptProjectCreator";
const pruneTaskLabel: string = 'prune';
export class TypeScriptProjectCreator extends JavaScriptProjectCreator {
public readonly preDeployTask: string = pruneTaskLabel;
constructor(functionAppPath: string, actionContext: IActionContext, runtime: ProjectRuntime | undefined) {
super(functionAppPath, actionContext, runtime);
this.funcignore = this.funcignore.concat('*.js.map', '*.ts', 'tsconfig.json');
}
public async onCreateNewProject(): Promise<void> {
await super.onCreateNewProject();
const tsconfigPath: string = path.join(this.functionAppPath, tsConfigFileName);
if (await confirmOverwriteFile(tsconfigPath)) {
const tsconfigJson: {} = {
compilerOptions: {
module: 'commonjs',
target: 'es6',
outDir: tsDefaultOutDir,
rootDir: '.',
sourceMap: true,
strict: false
}
};
await writeFormattedJson(tsconfigPath, tsconfigJson);
}
const packagePath: string = path.join(this.functionAppPath, 'package.json');
if (await confirmOverwriteFile(packagePath)) {
const packageJson: {} = {
name: path.basename(this.functionAppPath),
description: '',
version: '0.1.0',
scripts: {
build: 'tsc',
watch: 'tsc -w',
test: 'echo \"No tests yet...\"'
},
dependencies: {},
devDependencies: {
'@azure/functions': '^1.0.1-beta2',
typescript: '^3.3.3'
}
};
await writeFormattedJson(packagePath, packageJson);
const packageLockJson: {} = {
name: path.basename(this.functionAppPath),
version: '0.1.0',
lockfileVersion: 1,
requires: true,
dependencies: {
'@azure/functions': {
version: '1.0.1-beta2',
resolved: 'https://registry.npmjs.org/@azure/functions/-/functions-1.0.1-beta2.tgz',
integrity: 'sha512-ewVNxU2fqSCLbLuHwwvcL2ExgYNIhaztgHQfBShM9bpCBlAufTrvqlGnsEMfYv2F+BmJrkvhcDWE7E8cDz4X0g==',
dev: true
},
typescript: {
version: '3.3.3',
resolved: 'https://registry.npmjs.org/typescript/-/typescript-3.3.3.tgz',
integrity: 'sha512-Y21Xqe54TBVp+VDSNbuDYdGw0BpoR/Q6wo/+35M8PAU0vipahnyduJWirxxdxjsAkS7hue53x2zp8gz7F05u0A==',
dev: true
}
}
};
const packageLockPath: string = path.join(this.functionAppPath, 'package-lock.json');
await writeFormattedJson(packageLockPath, packageLockJson);
}
}
public getTasksJson(): {} {
const npmInstallTaskName: string = 'npm: install';
const npmBuildTaskName: string = 'npm: build';
return {
version: '2.0.0',
tasks: [
{
type: func,
command: hostStartCommand,
problemMatcher: funcWatchProblemMatcher,
isBackground: true,
dependsOn: npmBuildTaskName
},
{
type: 'npm',
script: 'build',
dependsOn: this.runtime === ProjectRuntime.v1 ? npmInstallTaskName : [extInstallTaskName, npmInstallTaskName],
problemMatcher: '$tsc'
},
{
type: 'shell',
label: pruneTaskLabel,
command: 'npm prune --production',
dependsOn: npmBuildTaskName,
problemMatcher: []
}
]
};
}
}

Просмотреть файл

@ -22,6 +22,7 @@ import { JavaScriptProjectCreator } from './JavaScriptProjectCreator';
import { ProjectCreatorBase } from './ProjectCreatorBase';
import { PythonProjectCreator } from './PythonProjectCreator';
import { ScriptProjectCreatorBase } from './ScriptProjectCreatorBase';
import { TypeScriptProjectCreator } from './TypeScriptProjectCreator';
export async function createNewProject(
actionContext: IActionContext,
@ -46,8 +47,9 @@ export async function createNewProject(
const previewDescription: string = localize('previewDescription', '(Preview)');
// Only display 'supported' languages that can be debugged in VS Code
const languagePicks: QuickPickItem[] = [
{ label: ProjectLanguage.JavaScript, description: '' },
{ label: ProjectLanguage.CSharp, description: '' },
{ label: ProjectLanguage.JavaScript },
{ label: ProjectLanguage.TypeScript },
{ label: ProjectLanguage.CSharp },
{ label: ProjectLanguage.Python, description: previewDescription },
{ label: ProjectLanguage.Java, description: previewDescription }
];
@ -102,6 +104,9 @@ export function getProjectCreator(language: string, functionAppPath: string, act
case ProjectLanguage.Python:
projectCreatorType = PythonProjectCreator;
break;
case ProjectLanguage.TypeScript:
projectCreatorType = TypeScriptProjectCreator;
break;
default:
projectCreatorType = ScriptProjectCreatorBase;
break;

Просмотреть файл

@ -87,3 +87,6 @@ export const funcPackCommand: string = `${func} ${packCommand}`;
export const funcWatchProblemMatcher: string = '$func-watch';
export const localhost: string = '127.0.0.1';
export const tsDefaultOutDir: string = 'dist';
export const tsConfigFileName: string = 'tsconfig.json';

Просмотреть файл

@ -59,6 +59,7 @@ export class FuncTaskProvider implements TaskProvider {
debugProvider = this._pythonDebugProvider;
break;
case ProjectLanguage.JavaScript:
case ProjectLanguage.TypeScript:
debugProvider = this._nodeDebugProvider;
break;
case ProjectLanguage.Java:

Просмотреть файл

@ -11,7 +11,7 @@ import { FuncDebugProviderBase } from './FuncDebugProviderBase';
export const defaultNodeDebugPort: number = 9229;
export const nodeDebugConfig: DebugConfiguration = {
name: localize('attachJS', 'Attach to JavaScript Functions'),
name: localize('attachNode', 'Attach to Node Functions'),
type: 'node',
request: 'attach',
port: defaultNodeDebugPort,

Просмотреть файл

@ -117,7 +117,7 @@ suite('Create New Project Tests', async function (this: ISuiteCallbackContext):
const typeScriptProject: string = 'TypeScriptProject';
test(typeScriptProject, async () => {
const projectPath: string = path.join(testFolderPath, typeScriptProject);
await testCreateNewProject(projectPath, ProjectLanguage.TypeScript, true);
await testCreateNewProject(projectPath, ProjectLanguage.TypeScript, false);
await validateVSCodeProjectFiles(projectPath, false);
});