Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: empty spaces uncorrectly detected as positional argument #626

Merged
merged 4 commits into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import mockFs from "mock-fs";
import { build } from "./build";
import { DEFAULT_CONFIG } from "../../config";
import { convertToNativePaths } from "../../jest.helpers.";
import { DEFAULT_CONFIG } from "../../../config";
import { convertToNativePaths } from "../../../jest.helpers.";

jest.mock("child_process", () => ({
execSync: jest.fn(),
Expand Down
36 changes: 2 additions & 34 deletions src/cli/commands/build.ts → src/cli/commands/build/build.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,15 @@
import path from "path";
import chalk from "chalk";
import { Command } from "commander";
import { DEFAULT_CONFIG } from "../../config";
import { detectProjectFolders, generateConfiguration } from "../../core/frameworks";
import { detectProjectFolders, generateConfiguration } from "../../../core/frameworks";
import {
configureOptions,
findUpPackageJsonDir,
isUserOption,
isUserOrConfigOption,
logger,
matchLoadedConfigName,
pathExists,
readWorkflowFile,
runCommand,
swaCliConfigFilename,
} from "../../core/utils";

export default function registerCommand(program: Command) {
program
.command("build [configName|appLocation]")
.usage("[configName|appLocation] [options]")
.description("build your project")
.option("-a, --app-location <path>", "the folder containing the source code of the front-end application", DEFAULT_CONFIG.appLocation)
.option("-i, --api-location <path>", "the folder containing the source code of the API application", DEFAULT_CONFIG.apiLocation)
.option("-O, --output-location <path>", "the folder containing the built source of the front-end application", DEFAULT_CONFIG.outputLocation)
.option("-A, --app-build-command <command>", "the command used to build your app", DEFAULT_CONFIG.appBuildCommand)
.option("-I, --api-build-command <command>", "the command used to build your api", DEFAULT_CONFIG.apiBuildCommand)
.option("--auto", "automatically detect how to build your app and api", false)
.action(async (positionalArg: string | undefined, _options: SWACLIConfig, command: Command) => {
const options = await configureOptions(positionalArg, command.optsWithGlobals(), command, "build");
if (positionalArg && !matchLoadedConfigName(positionalArg)) {
if (isUserOption("appLocation")) {
logger.error(`swa build <appLocation> cannot be when with --app-location option is also set.`);
logger.error(`You either have to use the positional argument or option, not both at the same time.`, true);
}

// If it's not the config name, then it's the app location
options.appLocation = positionalArg;
}

await build(options);
});
}
} from "../../../core/utils";

export async function build(options: SWACLIConfig) {
const workflowConfig = readWorkflowFile();
Expand Down
2 changes: 2 additions & 0 deletions src/cli/commands/build/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./build";
export { default as registerBuild } from "./register";
32 changes: 32 additions & 0 deletions src/cli/commands/build/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Command } from "commander";
import { DEFAULT_CONFIG } from "../../../config";
import { configureOptions, isUserOption, logger, matchLoadedConfigName } from "../../../core/utils";
import { build } from "./build";

export default function registerCommand(program: Command) {
program
.command("build [configName|appLocation]")
.usage("[configName|appLocation] [options]")
.description("build your project")
.option("-a, --app-location <path>", "the folder containing the source code of the front-end application", DEFAULT_CONFIG.appLocation)
.option("-i, --api-location <path>", "the folder containing the source code of the API application", DEFAULT_CONFIG.apiLocation)
.option("-O, --output-location <path>", "the folder containing the built source of the front-end application", DEFAULT_CONFIG.outputLocation)
.option("-A, --app-build-command <command>", "the command used to build your app", DEFAULT_CONFIG.appBuildCommand)
.option("-I, --api-build-command <command>", "the command used to build your api", DEFAULT_CONFIG.apiBuildCommand)
.option("--auto", "automatically detect how to build your app and api", false)
.action(async (positionalArg: string | undefined, _options: SWACLIConfig, command: Command) => {
positionalArg = positionalArg?.trim();
const options = await configureOptions(positionalArg, command.optsWithGlobals(), command, "build");
if (positionalArg && !matchLoadedConfigName(positionalArg)) {
if (isUserOption("appLocation")) {
logger.error(`swa build <appLocation> cannot be when with --app-location option is also set.`);
logger.error(`You either have to use the positional argument or option, not both at the same time.`, true);
}

// If it's not the config name, then it's the app location
options.appLocation = positionalArg;
}

await build(options);
});
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import child_process from "child_process";
import mockFs from "mock-fs";
import path from "path";
import { logger } from "../../core";
import * as accountModule from "../../core/account";
import * as deployClientModule from "../../core/deploy-client";
import { logger } from "../../../core";
import * as accountModule from "../../../core/account";
import * as deployClientModule from "../../../core/deploy-client";
import { deploy } from "./deploy";
import * as loginModule from "./login";
import * as loginModule from "../login/login";

const pkg = require(path.join(__dirname, "..", "..", "..", "package.json"));
const pkg = require(path.join(__dirname, "..", "..", "..", "..", "package.json"));

jest.mock("ora", () => {
return jest.fn();
});

jest.mock("../../core/utils/logger", () => {
jest.mock("../../../core/utils/logger", () => {
return {
logger: {
error: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,83 +1,22 @@
import chalk from "chalk";
import { spawn } from "child_process";
import { Command } from "commander";
import fs from "fs";
import ora, { Ora } from "ora";
import path from "path";
import { DEFAULT_CONFIG } from "../../config";
import {
configureOptions,
findSWAConfigFile,
getCurrentSwaCliConfigFromFile,
isUserOption,
logger,
logGiHubIssueMessageAndExit,
matchLoadedConfigName,
readWorkflowFile,
updateSwaCliConfigFile,
} from "../../core";
import { chooseOrCreateProjectDetails, getStaticSiteDeployment } from "../../core/account";
import { cleanUp, getDeployClientPath } from "../../core/deploy-client";
import { swaCLIEnv } from "../../core/env";
import { addSharedLoginOptionsToCommand, login } from "./login";

const packageInfo = require(path.join(__dirname, "..", "..", "..", "package.json"));

export default function registerCommand(program: Command) {
const deployCommand = program
.command("deploy [configName|outputLocation]")
.usage("[configName|outputLocation] [options]")
.description("deploy the current project to Azure Static Web Apps")
.option("-a, --app-location <path>", "the folder containing the source code of the front-end application", DEFAULT_CONFIG.appLocation)
.option("-i, --api-location <path>", "the folder containing the source code of the API application", DEFAULT_CONFIG.apiLocation)
.option("-O, --output-location <path>", "the folder containing the built source of the front-end application", DEFAULT_CONFIG.outputLocation)
.option(
"-w, --swa-config-location <swaConfigLocation>",
"the directory where the staticwebapp.config.json file is located",
DEFAULT_CONFIG.swaConfigLocation
)
.option("-d, --deployment-token <secret>", "the secret token used to authenticate with the Static Web Apps")
.option("-dr, --dry-run", "simulate a deploy process without actually running it", DEFAULT_CONFIG.dryRun)
.option("-pt, --print-token", "print the deployment token", false)
.option("--env [environment]", "the type of deployment environment where to deploy the project", DEFAULT_CONFIG.env)
.action(async (positionalArg: string | undefined, _options: SWACLIConfig, command: Command) => {
const options = await configureOptions(positionalArg, command.optsWithGlobals(), command, "deploy");
if (positionalArg && !matchLoadedConfigName(positionalArg)) {
if (isUserOption("outputLocation")) {
logger.error(`swa deploy <outputLocation> cannot be used when --output-location option is also set.`);
logger.error(`You either have to use the positional argument or option, not both at the same time.`, true);
}

// If it's not the config name, then it's the output location
options.outputLocation = positionalArg;
}

await deploy(options);
})
.addHelpText(
"after",
`
Examples:

Deploy using a deployment token
swa deploy ./dist/ --api-location ./api/ --deployment-token <token>
} from "../../../core";
import { chooseOrCreateProjectDetails, getStaticSiteDeployment } from "../../../core/account";
import { cleanUp, getDeployClientPath } from "../../../core/deploy-client";
import { swaCLIEnv } from "../../../core/env";
import { login } from "../login";

Deploy using a deployment token from env
SWA_CLI_DEPLOYMENT_TOKEN=123 swa deploy ./dist/ --api-location ./api/

Deploy using swa-cli.config.json file
swa deploy
swa deploy myconfig

Print the deployment token
swa deploy --print-token

Deploy to a specific environment
swa deploy --env production
`
);
addSharedLoginOptionsToCommand(deployCommand);
}
const packageInfo = require(path.join(__dirname, "..", "..", "..", "..", "package.json"));

export async function deploy(options: SWACLIConfig) {
const { SWA_CLI_DEPLOYMENT_TOKEN, SWA_CLI_DEBUG } = swaCLIEnv();
Expand Down
2 changes: 2 additions & 0 deletions src/cli/commands/deploy/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./deploy";
export { default as registerDeploy } from "./register";
62 changes: 62 additions & 0 deletions src/cli/commands/deploy/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Command } from "commander";
import { DEFAULT_CONFIG } from "../../../config";
import { configureOptions, isUserOption, logger, matchLoadedConfigName } from "../../../core";
import { addSharedLoginOptionsToCommand } from "../login";
import { deploy } from "./deploy";

export default function registerCommand(program: Command) {
const deployCommand = program
.command("deploy [configName|outputLocation]")
.usage("[configName|outputLocation] [options]")
.description("deploy the current project to Azure Static Web Apps")
.option("-a, --app-location <path>", "the folder containing the source code of the front-end application", DEFAULT_CONFIG.appLocation)
.option("-i, --api-location <path>", "the folder containing the source code of the API application", DEFAULT_CONFIG.apiLocation)
.option("-O, --output-location <path>", "the folder containing the built source of the front-end application", DEFAULT_CONFIG.outputLocation)
.option(
"-w, --swa-config-location <swaConfigLocation>",
"the directory where the staticwebapp.config.json file is located",
DEFAULT_CONFIG.swaConfigLocation
)
.option("-d, --deployment-token <secret>", "the secret token used to authenticate with the Static Web Apps")
.option("-dr, --dry-run", "simulate a deploy process without actually running it", DEFAULT_CONFIG.dryRun)
.option("-pt, --print-token", "print the deployment token", false)
.option("--env [environment]", "the type of deployment environment where to deploy the project", DEFAULT_CONFIG.env)
.action(async (positionalArg: string | undefined, _options: SWACLIConfig, command: Command) => {
positionalArg = positionalArg?.trim();
const options = await configureOptions(positionalArg, command.optsWithGlobals(), command, "deploy");
if (positionalArg && !matchLoadedConfigName(positionalArg)) {
if (isUserOption("outputLocation")) {
logger.error(`swa deploy <outputLocation> cannot be used when --output-location option is also set.`);
logger.error(`You either have to use the positional argument or option, not both at the same time.`, true);
}

// If it's not the config name, then it's the output location
options.outputLocation = positionalArg;
}

await deploy(options);
})
.addHelpText(
"after",
`
Examples:

Deploy using a deployment token
swa deploy ./dist/ --api-location ./api/ --deployment-token <token>

Deploy using a deployment token from env
SWA_CLI_DEPLOYMENT_TOKEN=123 swa deploy ./dist/ --api-location ./api/

Deploy using swa-cli.config.json file
swa deploy
swa deploy myconfig

Print the deployment token
swa deploy --print-token

Deploy to a specific environment
swa deploy --env production
`
);
addSharedLoginOptionsToCommand(deployCommand);
}
2 changes: 1 addition & 1 deletion src/cli/commands/docs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Command } from "commander";
import open from "open";

export default function registerDocs(program: Command) {
export function registerDocs(program: Command) {
program
.command("docs")
.description("open Azure Static Web Apps CLI documentations")
Expand Down
2 changes: 2 additions & 0 deletions src/cli/commands/init/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./init";
export { default as registerInit } from "./register";
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import fs from "fs";
import mockFs from "mock-fs";
import { init } from "./init";
import { DEFAULT_CONFIG } from "../../config";
import { swaCliConfigFilename } from "../../core/utils";
import { convertToNativePaths, convertToUnixPaths } from "../../jest.helpers.";
import { DEFAULT_CONFIG } from "../../../config";
import { swaCliConfigFilename } from "../../../core/utils";
import { convertToNativePaths, convertToUnixPaths } from "../../../jest.helpers.";

jest.mock("prompts", () => jest.fn());

Expand Down
30 changes: 3 additions & 27 deletions src/cli/commands/init.ts → src/cli/commands/init/init.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,16 @@
import chalk from "chalk";
import { Command } from "commander";
import path from "path";
import process from "process";
import { promptOrUseDefault } from "../../core/prompts";
import { promptOrUseDefault } from "../../../core/prompts";
import {
configureOptions,
dasherize,
hasConfigurationNameInConfigFile,
isUserOption,
logger,
swaCliConfigFileExists,
swaCliConfigFilename,
writeConfigFile,
} from "../../core/utils";
import { detectProjectFolders, generateConfiguration, isDescendantPath } from "../../core/frameworks";

export default function registerCommand(program: Command) {
program
.command("init [configName]")
.usage("[configName] [options]")
.description("initialize a new static web app project")
.option("-y, --yes", "answer yes to all prompts (disable interactive mode)", false)
.action(async (configName: string | undefined, _options: SWACLIConfig, command: Command) => {
const options = await configureOptions(undefined, command.optsWithGlobals(), command, "init", false);
if (configName) {
if (isUserOption("configName")) {
logger.error(`swa init <configName> cannot be used when --config-name option is also set.`);
logger.error(`You either have to use the positional argument or option, not both at the same time.`, true);
}

options.configName = configName;
}

await init(options, !process.env.SWA_CLI_INTERNAL_COMMAND);
});
}
} from "../../../core/utils";
import { detectProjectFolders, generateConfiguration, isDescendantPath } from "../../../core/frameworks";

export async function init(options: SWACLIConfig, showHints: boolean = true) {
const configFilePath = options.config!;
Expand Down
25 changes: 25 additions & 0 deletions src/cli/commands/init/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Command } from "commander";
import process from "process";
import { configureOptions, isUserOption, logger } from "../../../core/utils";
import { init } from "./init";

export default function registerCommand(program: Command) {
program
.command("init [configName]")
.usage("[configName] [options]")
.description("initialize a new static web app project")
.option("-y, --yes", "answer yes to all prompts (disable interactive mode)", false)
.action(async (configName: string | undefined, _options: SWACLIConfig, command: Command) => {
const options = await configureOptions(undefined, command.optsWithGlobals(), command, "init", false);
if (configName) {
if (isUserOption("configName")) {
logger.error(`swa init <configName> cannot be used when --config-name option is also set.`);
logger.error(`You either have to use the positional argument or option, not both at the same time.`, true);
}

options.configName = configName;
}

await init(options, !process.env.SWA_CLI_INTERNAL_COMMAND);
});
}
2 changes: 2 additions & 0 deletions src/cli/commands/login/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./login";
export { default as registerLogin, addSharedLoginOptionsToCommand } from "./register";