Repository: serverless/serverless-azure-functions (ts)

Issue:
Node runtime should be set to node
# This is a Bug Report

## Description

Generated local.settings.json uses `nodejs` as the `FUNCTIONS_WORKER_RUNTIME` instead of the valid value of `node`.

Similar or dependent issues:

Might be related to: #437 

/cc jclaessens97 who raised this at https://github.com/Azure/azure-functions-core-tools/issues/2002

Pull request:
fix: Fix runtime language in generated local settings
<!--
1. Please check out and follow our Contributing Guidelines: https://github.com/serverless/serverless-azure-functions/CONTRIBUTING.md
2. Do not remove any section of the template. If something is not applicable leave it empty but leave it in the PR
3. Please follow the template, otherwise we'll have to ask you to update it and it will take longer until your PR is merged
-->

## What did you implement:

Fix generated node runtime version for local.settings.json

Closes #467 

<!--
Briefly describe the feature if no issue exists for this PR
-->

## How did you implement it:

Re-used a function that was being used to set the worker runtime in app settings and added it to the `runtime.ts` file for broader use

<!--
If this is a nontrivial change please briefly describe your implementation so its easy for us to understand and review your code.
-->

## How can we verify it:

1. `sls create -t azure-nodejs`
2. `sls offline`

<!--
Add any applicable config, commands, screenshots or other resources
to make it easy for us to verify this works. The easier you make it for us
to review a PR, the faster we can review and merge it.

Examples:
* serverless.yml - Fully functioning to easily deploy changes
* Screenshots - Showing the difference between your output and the master
* Cloud Configuration - List cloud resources and show that the correct configuration is in place
* Other - Anything else that comes to mind to help us evaluate
-->

## Todos:

_**Note: Run `npm run test:ci` to run all validation checks on proposed changes**_

- [x] Ensure there are no lint errors.  
       **Validate via `npm run lint`**  
       _Note: Some reported issues can be automatically fixed by running `npm run lint:fix`_
- [x] Write tests and confirm existing functionality is not broken.  
       **Validate via `npm test`**
- [x] Write documentation
- [x] Provide verification config / commands / resources
- [x] Enable "Allow edits from maintainers" for this PR
- [x] Update the messages below

**_Is this ready for review?:_** YES
**_Is it a breaking change?:_** NO


Patch:
diff --git a/src/armTemplates/resources/functionApp.ts b/src/armTemplates/resources/functionApp.ts
index 61685bf..bc5b561 100644
--- a/src/armTemplates/resources/functionApp.ts
+++ b/src/armTemplates/resources/functionApp.ts
@@ -1,4 +1,4 @@
-import { dockerImages, getRuntimeLanguage, getRuntimeVersion, FunctionAppOS, isNodeRuntime, Runtime, RuntimeLanguage } from "../../config/runtime";
+import { dockerImages, getRuntimeLanguage, getRuntimeVersion, FunctionAppOS, isNodeRuntime, Runtime, RuntimeLanguage, getFunctionWorkerRuntime } from "../../config/runtime";
 import { ArmParameter, ArmParameters, ArmParamType, ArmResourceTemplate, ArmResourceTemplateGenerator, DefaultArmParams } from "../../models/armTemplates";
 import { FunctionAppConfig, ServerlessAzureConfig } from "../../models/serverless";
 import { AzureNamingService, AzureNamingServiceOptions } from "../../services/namingService";
@@ -139,7 +139,7 @@ export class FunctionAppResource implements ArmResourceTemplateGenerator {
         value: (isLinuxRuntime) ? this.getLinuxFxVersion(config) : undefined,
       },
       functionAppWorkerRuntime: {
-        value: this.getFunctionWorkerRuntime(runtime),
+        value: getFunctionWorkerRuntime(runtime),
       },
       functionAppExtensionVersion: {
         value: resourceConfig.extensionVersion,
@@ -254,14 +254,6 @@ export class FunctionAppResource implements ArmResourceTemplateGenerator {
     return appSettings;
   }
 
-  private getFunctionWorkerRuntime(runtime: Runtime): string {
-    const language = getRuntimeLanguage(runtime);
-    if (language === RuntimeLanguage.NODE){
-      return "node";
-    }
-    return language;
-  }
-
   private getLinuxFxVersion(config: ServerlessAzureConfig): string {
     const { runtime } = config.provider;
     try {
diff --git a/src/config/runtime.ts b/src/config/runtime.ts
index f7f757c..7ff39b1 100644
--- a/src/config/runtime.ts
+++ b/src/config/runtime.ts
@@ -73,6 +73,14 @@ export function getRuntimeLanguage(runtime: Runtime): string {
   throw new Error(`Runtime ${runtime} not included in supportedRuntimes`);
 }
 
+export function getFunctionWorkerRuntime(runtime: Runtime): string {
+  const language = getRuntimeLanguage(runtime);
+  if (language === RuntimeLanguage.NODE){
+    return "node";
+  }
+  return language;
+}
+
 export enum FunctionAppOS {
   WINDOWS = "windows",
   LINUX = "linux"
diff --git a/src/services/offlineService.ts b/src/services/offlineService.ts
index 89faeb9..18916c3 100644
--- a/src/services/offlineService.ts
+++ b/src/services/offlineService.ts
@@ -2,7 +2,7 @@ import fs from "fs";
 import Serverless from "serverless";
 import { BaseService } from "./baseService";
 import { PackageService } from "./packageService";
-import { getRuntimeLanguage, isCompiledRuntime, BuildMode } from "../config/runtime";
+import { getRuntimeLanguage, isCompiledRuntime, BuildMode, getFunctionWorkerRuntime } from "../config/runtime";
 import { Utils } from "../shared/utils";
 import { CompilerService } from "./compilerService";
 import { constants } from "../shared/constants";
@@ -17,7 +17,7 @@ export class OfflineService extends BaseService {
       IsEncrypted: false,
       Values: {
         AzureWebJobsStorage: "UseDevelopmentStorage=true",
-        FUNCTIONS_WORKER_RUNTIME: getRuntimeLanguage(this.config.provider.runtime),
+        FUNCTIONS_WORKER_RUNTIME: getFunctionWorkerRuntime(this.config.provider.runtime),
       }
     }),
   }


Test patch:
diff --git a/src/config/runtime.test.ts b/src/config/runtime.test.ts
index 9363bda..6d73ba2 100644
--- a/src/config/runtime.test.ts
+++ b/src/config/runtime.test.ts
@@ -1,4 +1,4 @@
-import { Runtime, isNodeRuntime, isPythonRuntime, getRuntimeVersion, getRuntimeLanguage } from "./runtime";
+import { Runtime, isNodeRuntime, isPythonRuntime, getRuntimeVersion, getRuntimeLanguage, getFunctionWorkerRuntime } from "./runtime";
 
 
 describe("Runtime", () => {
@@ -33,4 +33,14 @@ describe("Runtime", () => {
     expect(getRuntimeLanguage(Runtime.PYTHON37)).toBe("python");
     expect(getRuntimeLanguage(Runtime.PYTHON38)).toBe("python");
   });
+
+  it("gets function worker runtime", () => {
+    expect(getFunctionWorkerRuntime(Runtime.NODE10)).toBe("node");
+    expect(getFunctionWorkerRuntime(Runtime.NODE12)).toBe("node");
+    expect(getFunctionWorkerRuntime(Runtime.PYTHON36)).toBe("python");
+    expect(getFunctionWorkerRuntime(Runtime.PYTHON37)).toBe("python");
+    expect(getFunctionWorkerRuntime(Runtime.PYTHON38)).toBe("python");
+    expect(getFunctionWorkerRuntime(Runtime.DOTNET31)).toBe("dotnet");
+    expect(getFunctionWorkerRuntime(Runtime.DOTNET22)).toBe("dotnet");
+  });
 });