Skip to content

Commit 5774c41

Browse files
committed
feat: add select option for apiLanguage flags
1 parent 32e3dc0 commit 5774c41

File tree

4 files changed

+112
-54
lines changed

4 files changed

+112
-54
lines changed

src/cli/commands/deploy.ts

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ import {
99
configureOptions,
1010
findSWAConfigFile,
1111
getCurrentSwaCliConfigFromFile,
12+
getDefaultVersion,
1213
isUserOption,
14+
isUserOrConfigOption,
1315
logger,
1416
logGiHubIssueMessageAndExit,
1517
matchLoadedConfigName,
1618
readWorkflowFile,
1719
updateSwaCliConfigFile,
1820
} from "../../core";
1921
import { chooseOrCreateProjectDetails, getStaticSiteDeployment } from "../../core/account";
20-
import { DEFAULT_DOTNET_ISOLATED_VERSION, DEFAULT_DOTNET_VERSION, DEFAULT_NODE_VERSION, DEFAULT_PYTHON_VERSION } from "../../core/constants";
2122
import { cleanUp, getDeployClientPath } from "../../core/deploy-client";
2223
import { swaCLIEnv } from "../../core/env";
2324
import { addSharedLoginOptionsToCommand, login } from "./login";
@@ -32,8 +33,8 @@ export default function registerCommand(program: Command) {
3233
.option("-a, --app-location <path>", "the folder containing the source code of the front-end application", DEFAULT_CONFIG.appLocation)
3334
.option("-i, --api-location <path>", "the folder containing the source code of the API application", DEFAULT_CONFIG.apiLocation)
3435
.option("-O, --output-location <path>", "the folder containing the built source of the front-end application", DEFAULT_CONFIG.outputLocation)
35-
.option("-l, --api-language <apiLanguage>", "the runtime language of the function/api")
36-
.option("-v, --api-version <apiVersion>", "the version of the function runtime language")
36+
.option("-l, --api-language <apiLanguage>", "the runtime language of the function/api", DEFAULT_CONFIG.apiLanguage)
37+
.option("-f, --api-version <apiVersion>", "the version of the function runtime language", DEFAULT_CONFIG.apiVersion)
3738
.option(
3839
"-w, --swa-config-location <swaConfigLocation>",
3940
"the directory where the staticwebapp.config.json file is located",
@@ -138,33 +139,6 @@ export async function deploy(options: SWACLIConfig) {
138139
logger.log(` ${chalk.green(resolvedApiLocation)}`);
139140
logger.log(``);
140141
}
141-
if (!apiLanguage) {
142-
apiLanguage = DEFAULT_CONFIG.apiLanguage;
143-
apiVersion = DEFAULT_CONFIG.apiVersion;
144-
logger.log(`Consider providing api-language and version using --api-language and --api-version flags,
145-
otherwise default values apiLanguage: ${apiLanguage} and apiVersion: ${apiVersion} will apply`);
146-
} else if (apiLanguage && !apiVersion) {
147-
switch (apiLanguage) {
148-
case "node":
149-
apiVersion = DEFAULT_NODE_VERSION;
150-
break;
151-
case "python":
152-
apiVersion = DEFAULT_PYTHON_VERSION;
153-
break;
154-
case "dotnet":
155-
apiVersion = DEFAULT_DOTNET_VERSION;
156-
break;
157-
case "dotnetisolated":
158-
apiVersion = DEFAULT_DOTNET_ISOLATED_VERSION;
159-
break;
160-
default:
161-
apiLanguage = DEFAULT_CONFIG.apiLanguage;
162-
apiVersion = DEFAULT_CONFIG.apiVersion;
163-
break;
164-
}
165-
logger.silly(`Api language "${apiLanguage}" is provided but api version is not provided.
166-
Assuming default version "${apiVersion}"`);
167-
}
168142
} else {
169143
// otherwise, check if the default api folder exists and print a warning
170144
const apiFolder = await findApiFolderInPath(appLocation);
@@ -177,6 +151,15 @@ export async function deploy(options: SWACLIConfig) {
177151
}
178152
}
179153

154+
if (!isUserOrConfigOption("apiLanguage")) {
155+
logger.log(`Consider providing api-language and version using --api-language and --api-version flags,
156+
otherwise default values apiLanguage: ${apiLanguage} and apiVersion: ${apiVersion} will apply`);
157+
} else if (!isUserOrConfigOption("apiVersion")) {
158+
apiVersion = getDefaultVersion(apiLanguage);
159+
logger.log(`Api language "${apiLanguage}" is provided but api version is not provided.
160+
Assuming default version "${apiVersion}"`);
161+
}
162+
180163
// resolve the deployment token
181164
if (deploymentToken) {
182165
deploymentToken = deploymentToken;
@@ -362,7 +345,7 @@ export async function deploy(options: SWACLIConfig) {
362345
else if (line.includes("[31m")) {
363346
if (line.includes("Cannot deploy to the function app because Function language info isn't provided.")) {
364347
line = chalk.red(
365-
`Cannot deploy to the function app because Function language info isn't provided, use flags "--api-language" and "--api-version" or add a "platform.apiRuntime" property to your staticwebapp.config.json file, or create one in ${options.outputLocation!}. Please consult the documentation for more information about staticwebapp.config.json: https://docs.microsoft.com/azure/static-web-apps/configuration`
348+
`Cannot deploy to the function app because Function language info isn't provided, use flags "--api-language" and "--api-version" or add a "platform.apiRuntime" property to your staticwebapp.config.json file, or create one in ${options.outputLocation!}. Please consult the documentation for more information about staticwebapp.config.json: https://learn.microsoft.com/en-us/azure/static-web-apps/build-configuration?tabs=github-actions#skip-building-the-api`
366349
);
367350
}
368351

src/cli/commands/init.ts

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import chalk from "chalk";
22
import { Command } from "commander";
33
import path from "path";
44
import process from "process";
5+
import prompts from "prompts";
56
import { promptOrUseDefault } from "../../core/prompts";
67
import {
78
configureOptions,
@@ -175,7 +176,8 @@ async function promptConfigSettings(disablePrompts: boolean, detectedConfig: Fra
175176
value = value.trim();
176177
return value === "" ? undefined : value;
177178
};
178-
const response = await promptOrUseDefault(disablePrompts, [
179+
180+
let response = await promptOrUseDefault(disablePrompts, [
179181
{
180182
type: "text",
181183
name: "appLocation",
@@ -200,20 +202,6 @@ async function promptConfigSettings(disablePrompts: boolean, detectedConfig: Fra
200202
initial: detectedConfig.apiLocation,
201203
format: trimValue,
202204
},
203-
{
204-
type: "text",
205-
name: "apiLanguage",
206-
message: "What's your API language? (optional)",
207-
initial: detectedConfig.apiLanguage,
208-
format: trimValue,
209-
},
210-
{
211-
type: "text",
212-
name: "apiVersion",
213-
message: "What's your API version? (optional)",
214-
initial: detectedConfig.apiVersion,
215-
format: trimValue,
216-
},
217205
{
218206
type: "text",
219207
name: "appBuildCommand",
@@ -242,10 +230,85 @@ async function promptConfigSettings(disablePrompts: boolean, detectedConfig: Fra
242230
initial: detectedConfig.appDevserverUrl,
243231
format: trimValue,
244232
},
233+
{
234+
type: null,
235+
name: "apiLanguage",
236+
},
237+
{
238+
type: null,
239+
name: "apiVersion",
240+
},
245241
]);
242+
243+
if (response.apiLocation) {
244+
const apiLanguagePrompt = await prompts([
245+
{
246+
type: "select",
247+
name: "apiLanguage",
248+
message: "What's your API language? (optional)",
249+
choices: [
250+
{ title: "Node.js", value: "node" },
251+
{ title: "Python", value: "python" },
252+
{ title: "Dotnet", value: "dotnet" },
253+
{ title: "Dotnet isolated", value: "dotnet-isolated" },
254+
],
255+
},
256+
]);
257+
258+
response.apiLanguage = apiLanguagePrompt.apiLanguage;
259+
260+
const apiVersionPrompt = await prompts([
261+
{
262+
type: "select",
263+
name: "apiVersion",
264+
message: "What's your API version? (optional)",
265+
choices: getChoicesForApiLanguage(response.apiLanguage),
266+
},
267+
]);
268+
269+
response.apiVersion = apiVersionPrompt.apiVersion;
270+
}
271+
246272
return response;
247273
}
248274

275+
function getChoicesForApiLanguage(apiLanguage: string) {
276+
// Refer to this for functions and versions - https://learn.microsoft.com/en-us/azure/static-web-apps/configuration#selecting-the-api-language-runtime-version
277+
let choices = [];
278+
switch (apiLanguage) {
279+
case "node":
280+
choices = [
281+
{ title: "16", value: "16" },
282+
{ title: "14", value: "14" },
283+
{ title: "12", value: "12" },
284+
];
285+
break;
286+
case "python":
287+
choices = [
288+
{ title: "3.8", value: "3.8" },
289+
{ title: "3.9", value: "3.9" },
290+
];
291+
break;
292+
case "dotnet":
293+
choices = [
294+
{ title: "6.0", value: "6.0" },
295+
{ title: "3.1", value: "3.1" },
296+
];
297+
break;
298+
case "dotnet-isolated":
299+
choices = [{ title: "6.0", value: "6.0" }];
300+
break;
301+
default:
302+
choices = [
303+
{ title: "16", value: "16" },
304+
{ title: "14", value: "14" },
305+
{ title: "12", value: "12" },
306+
];
307+
break;
308+
}
309+
return choices;
310+
}
311+
249312
function printFrameworkConfig(config: FrameworkConfig) {
250313
logger.log(chalk.bold("\nDetected configuration for your app:"));
251314
logger.log(`- Framework(s): ${chalk.green(config.name ?? "none")}`);

src/core/frameworks/detect.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ export async function generateConfiguration(app?: DetectedFolder, api?: Detected
4343
logger.silly(`Built API location "${computedApiLocation}" does not match root API location ${api.rootPath}, which is not supported yet`);
4444
}
4545
config.apiLocation = removeTrailingPathSep(api.rootPath);
46-
// config.apiLanguage = api.frameworks[0].name; //todo:check if the detected framework is valid or not
47-
config.apiVersion = getDefaultVersion(config.apiLanguage);
4846
}
4947

5048
const appRootPath = app && removeTrailingPathSep(app.rootPath);
@@ -163,7 +161,6 @@ export async function detectFrameworks(projectFiles: string[], frameworks: Frame
163161
detectedFrameworks.push({ ...framework, rootPaths });
164162
}
165163
}
166-
167164
detectedFrameworks = await asyncFilter(
168165
detectedFrameworks,
169166
async (framework) => (await matchPackages(framework)) && (await matchContains(framework, projectFiles))
@@ -395,11 +392,12 @@ export function formatDetectedFolders(folders: DetectedFolder[], type: string):
395392
`- ${folders.map((f) => `${f.rootPath} (${f.frameworks.map((fr) => fr.name).join(", ")})`).join("\n- ")}`
396393
);
397394
}
398-
function getDefaultVersion(apiLanguage: string): string {
395+
export function getDefaultVersion(apiLanguage: string | undefined): string {
399396
let apiVersion = "16";
400-
apiLanguage = apiLanguage.toLowerCase();
397+
if (!apiLanguage) apiLanguage = "node";
398+
// apiLanguage = apiLanguage.toLowerCase();
401399
switch (apiLanguage) {
402-
case "node.js":
400+
case "node":
403401
apiVersion = DEFAULT_NODE_VERSION;
404402
break;
405403
case "python":
@@ -408,7 +406,7 @@ function getDefaultVersion(apiLanguage: string): string {
408406
case "dotnet":
409407
apiVersion = DEFAULT_DOTNET_VERSION;
410408
break;
411-
case "dotnetisolated" || "dotnet isolated":
409+
case "dotnetisolated" || "dotnet isolated" || "dotnet-isolated":
412410
apiVersion = DEFAULT_DOTNET_ISOLATED_VERSION;
413411
break;
414412
default:

src/core/frameworks/frameworks.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ export const apiFrameworks: FrameworkDefinition[] = [
55
files: ["package.json", "host.json"],
66
config: {
77
apiBuildCommand: "npm run build --if-present",
8-
apiLanguage: "",
8+
apiLanguage: "node.js",
9+
apiVersion: "16",
910
},
1011
},
1112
{
@@ -25,6 +26,17 @@ export const apiFrameworks: FrameworkDefinition[] = [
2526
files: ["*.?(csproj|fsproj)", "host.json"],
2627
config: {
2728
apiBuildCommand: "dotnet publish -c Release",
29+
apiLanguage: "dotnet",
30+
apiVersion: "6.0",
31+
},
32+
},
33+
{
34+
id: "dotnet-isolated",
35+
name: ".NET",
36+
files: ["*.?(csproj|fsproj)", "host.json"],
37+
config: {
38+
apiLanguage: "dotnet-isolated",
39+
apiVersion: "6.0",
2840
},
2941
},
3042
{
@@ -33,6 +45,8 @@ export const apiFrameworks: FrameworkDefinition[] = [
3345
files: ["?(requirements.txt|pyproject.toml|runtime.txt|setup.py)", "host.json"],
3446
config: {
3547
// Nothing to setup, but we need to know the apiLocation (rootPath)
48+
apiLanguage: "python",
49+
apiVersion: "3.9",
3650
},
3751
},
3852
];

0 commit comments

Comments
 (0)