From fd46b5ab13ba8d22903da0f379bd1f79981b04b4 Mon Sep 17 00:00:00 2001 From: Eric Jizba Date: Mon, 20 May 2024 11:04:07 -0700 Subject: [PATCH] Update Node.js project templates 1. Turn on http streaming by default for v4 model 2. Update default Node types for TypeScript projects (Node 20 has been GA for a few months now) 3. Support hot reload for debugging by default --- .../JavaScriptProjectCreateStep.ts | 30 +++++++++++++++++-- .../TypeScriptProjectCreateStep.ts | 26 +++++++++++----- .../TypeScriptInitVSCodeStep.ts | 15 +++++++++- src/debug/NodeDebugProvider.ts | 1 + test/project/validateProject.ts | 1 + 5 files changed, 62 insertions(+), 11 deletions(-) diff --git a/src/commands/createNewProject/ProjectCreateStep/JavaScriptProjectCreateStep.ts b/src/commands/createNewProject/ProjectCreateStep/JavaScriptProjectCreateStep.ts index 17ea2dc20..5aa122367 100644 --- a/src/commands/createNewProject/ProjectCreateStep/JavaScriptProjectCreateStep.ts +++ b/src/commands/createNewProject/ProjectCreateStep/JavaScriptProjectCreateStep.ts @@ -21,10 +21,16 @@ export const azureFunctionsDependencyVersion: string = '^4.0.0'; export class JavaScriptProjectCreateStep extends ScriptProjectCreateStep { protected gitignore: string = nodeGitignore; + protected functionSubpath: string; + protected shouldAddIndexFile: boolean; constructor() { super(); this.funcignore.push('*.js.map', '*.ts', 'tsconfig.json'); + // default functionSubpath value is a string + this.functionSubpath = getWorkspaceSetting(functionSubpathSetting) as string; + // index file only supported when using default folder structure + this.shouldAddIndexFile = this.functionSubpath === 'src/functions'; } public async executeCore(context: IProjectWizardContext, progress: Progress<{ message?: string | undefined; increment?: number | undefined }>): Promise { @@ -35,6 +41,10 @@ export class JavaScriptProjectCreateStep extends ScriptProjectCreateStep { await AzExtFsExtra.writeJSON(packagePath, this.getPackageJson(context)); } await this._installDependencies(context.projectPath); + + if (isNodeV4Plus(context) && this.shouldAddIndexFile) { + await this.addIndexFile(context); + } } private async _installDependencies(projectPath: string): Promise { @@ -56,9 +66,11 @@ export class JavaScriptProjectCreateStep extends ScriptProjectCreateStep { }; if (isNodeV4Plus(context)) { - // default functionSubpath value is a string - const functionSubpath: string = getWorkspaceSetting(functionSubpathSetting) as string; - packageJson.main = path.posix.join(functionSubpath, '*.js'); + if (this.shouldAddIndexFile) { + packageJson.main = 'src/{index.js,functions/*.js}'; + } else { + packageJson.main = path.posix.join(this.functionSubpath, '*.js'); + } } return packageJson; @@ -83,6 +95,18 @@ export class JavaScriptProjectCreateStep extends ScriptProjectCreateStep { protected getPackageJsonDevDeps(_context: IProjectWizardContext): { [key: string]: string } { return {}; } + + protected async addIndexFile(context: IProjectWizardContext): Promise { + const indexPath: string = path.join(context.projectPath, 'src', 'index.js'); + if (await confirmOverwriteFile(context, indexPath)) { + await AzExtFsExtra.writeFile(indexPath, `const { app } = require('@azure/functions'); + +app.setup({ + enableHttpStream: true, +}); +`); + } + } } /** diff --git a/src/commands/createNewProject/ProjectCreateStep/TypeScriptProjectCreateStep.ts b/src/commands/createNewProject/ProjectCreateStep/TypeScriptProjectCreateStep.ts index cf68308fe..9570f1fc3 100644 --- a/src/commands/createNewProject/ProjectCreateStep/TypeScriptProjectCreateStep.ts +++ b/src/commands/createNewProject/ProjectCreateStep/TypeScriptProjectCreateStep.ts @@ -7,11 +7,10 @@ import { AzExtFsExtra } from '@microsoft/vscode-azext-utils'; import * as path from 'path'; import { type Progress } from 'vscode'; import { FuncVersion } from '../../../FuncVersion'; -import { functionSubpathSetting, tsConfigFileName, tsDefaultOutDir } from '../../../constants'; +import { tsConfigFileName, tsDefaultOutDir } from '../../../constants'; import { localize } from '../../../localize'; import { confirmOverwriteFile } from '../../../utils/fs'; import { isNodeV4Plus } from '../../../utils/programmingModelUtils'; -import { getWorkspaceSetting } from '../../../vsCodeConfig/settings'; import { type IProjectWizardContext } from '../IProjectWizardContext'; import { JavaScriptProjectCreateStep } from './JavaScriptProjectCreateStep'; @@ -38,11 +37,12 @@ export class TypeScriptProjectCreateStep extends JavaScriptProjectCreateStep { protected getPackageJson(context: IProjectWizardContext): { [key: string]: unknown } { const packageJson = super.getPackageJson(context); if (isNodeV4Plus(context)) { - // default functionSubpath value is a string - const functionSubpath: string = getWorkspaceSetting(functionSubpathSetting) as string; - // this is set in the super class, but we want to override it - packageJson.main = path.posix.join('dist', functionSubpath, '*.js'); + if (this.shouldAddIndexFile) { + packageJson.main = 'dist/src/{index.js,functions/*.js}'; + } else { + packageJson.main = path.posix.join('dist', this.functionSubpath, '*.js'); + } } return packageJson; @@ -71,7 +71,7 @@ export class TypeScriptProjectCreateStep extends JavaScriptProjectCreateStep { switch (context.version) { case FuncVersion.v4: funcTypesVersion = '3'; - nodeTypesVersion = isNodeV4Plus(context) ? '18' : '16'; + nodeTypesVersion = '20'; break; case FuncVersion.v3: funcTypesVersion = '2'; @@ -96,4 +96,16 @@ export class TypeScriptProjectCreateStep extends JavaScriptProjectCreateStep { devDeps['rimraf'] = '^5.0.0'; return devDeps; } + + protected async addIndexFile(context: IProjectWizardContext): Promise { + const indexPath: string = path.join(context.projectPath, 'src', 'index.ts'); + if (await confirmOverwriteFile(context, indexPath)) { + await AzExtFsExtra.writeFile(indexPath, `import { app } from '@azure/functions'; + +app.setup({ + enableHttpStream: true, +}); +`); + } + } } diff --git a/src/commands/initProjectForVSCode/InitVSCodeStep/TypeScriptInitVSCodeStep.ts b/src/commands/initProjectForVSCode/InitVSCodeStep/TypeScriptInitVSCodeStep.ts index 5479d61e7..64b62654e 100644 --- a/src/commands/initProjectForVSCode/InitVSCodeStep/TypeScriptInitVSCodeStep.ts +++ b/src/commands/initProjectForVSCode/InitVSCodeStep/TypeScriptInitVSCodeStep.ts @@ -15,6 +15,7 @@ import { JavaScriptInitVSCodeStep } from "./JavaScriptInitVSCodeStep"; const npmPruneTaskLabel: string = convertToFunctionsTaskLabel('npm prune'); const npmInstallTaskLabel: string = convertToFunctionsTaskLabel('npm install'); const npmBuildTaskLabel: string = convertToFunctionsTaskLabel('npm build'); +const npmWatchTaskLabel: string = convertToFunctionsTaskLabel('npm watch'); const npmCleanTaskLabel: string = convertToFunctionsTaskLabel('npm clean'); export class TypeScriptInitVSCodeStep extends JavaScriptInitVSCodeStep { @@ -41,7 +42,7 @@ export class TypeScriptInitVSCodeStep extends JavaScriptInitVSCodeStep { command: hostStartCommand, problemMatcher: getFuncWatchProblemMatcher(language), isBackground: true, - dependsOn: npmBuildTaskLabel + dependsOn: npmWatchTaskLabel }, { type: 'shell', @@ -50,6 +51,18 @@ export class TypeScriptInitVSCodeStep extends JavaScriptInitVSCodeStep { dependsOn: this.hasCleanScript ? npmCleanTaskLabel : installDependsOn, problemMatcher: '$tsc' }, + { + type: 'shell', + label: npmWatchTaskLabel, + command: 'npm run watch', + dependsOn: this.hasCleanScript ? npmCleanTaskLabel : installDependsOn, + problemMatcher: "$tsc-watch", + group: { + kind: "build", + isDefault: true + }, + isBackground: true + }, { type: 'shell', label: npmInstallTaskLabel, diff --git a/src/debug/NodeDebugProvider.ts b/src/debug/NodeDebugProvider.ts index ab78bfeb9..28825b3aa 100644 --- a/src/debug/NodeDebugProvider.ts +++ b/src/debug/NodeDebugProvider.ts @@ -14,6 +14,7 @@ export const nodeDebugConfig: DebugConfiguration = { name: localize('attachNode', 'Attach to Node Functions'), type: 'node', request: 'attach', + restart: true, port: defaultNodeDebugPort, preLaunchTask: hostStartTaskName }; diff --git a/test/project/validateProject.ts b/test/project/validateProject.ts index f10e4c309..8957f4607 100644 --- a/test/project/validateProject.ts +++ b/test/project/validateProject.ts @@ -69,6 +69,7 @@ export function getTypeScriptValidateOptions(options?: { version?: FuncVersion, ], expectedTasks: [ 'npm build (functions)', + 'npm watch (functions)', 'npm install (functions)', 'npm prune (functions)', 'host start'