Skip to content

Commit

Permalink
Fix: Revert removal of use arguments and update CLI build commands (#769
Browse files Browse the repository at this point in the history
)

* Add default argument to cli.

* Change wordings in message.

* Change in the flag validator messages.

* Add new messages to InvalidArgumentErrors.
Exit in redLogger.
Add the flag in the validators.

* Change commands in package.json.

* Fix bug.

* change order of build

* Change order of dev build process.

* Update build-cli command

---------

Co-authored-by: sayedtaqui <sayedwp@gmail.com>
  • Loading branch information
amovar18 and mohdsayed authored Jul 24, 2024
1 parent d4cbda3 commit cc98d10
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 57 deletions.
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
"scripts": {
"build-storybook": "storybook build",
"build:all": "npm-run-all **:build ",
"tsc-packages:build": "npm run i18n:build && npm run common:build && npm run library-detection:build && npm run design-system:build && npm run analysis-utils:build",
"tsc-packages:dev": "run-p i18n:dev common:dev library-detection:dev design-system:dev analysis-utils:dev",
"build-cli": "npm run tsc-packages:build && npm run cli-dashboard:build && npm run cli:build",
"tsc-packages:build": "npm run i18n:build && npm run common:build && npm run design-system:build && npm run library-detection:build && npm run analysis-utils:build",
"tsc-packages:dev": "run-p i18n:dev common:dev design-system:dev library-detection:dev analysis-utils:dev",
"publish:all:local": "npm run build:all && npm run publish:local --workspaces",
"unpublish:all:local": "npm run unpublish:local --workspaces",
"publish:all:remote": "npm run build:all && npm run publish:remote --workspaces",
Expand All @@ -18,19 +17,20 @@
"common:prebuild": "npm run build:remove -w @google-psat/common",
"common:build": "npm run common:prebuild && npm run build -w @google-psat/common",
"common:dev": "npm run dev -w @google-psat/common",
"library-detection:prebuild": "npm run build:remove -w @google-psat/library-detection",
"library-detection:build": "npm run library-detection:prebuild && npm run build -w @google-psat/library-detection",
"library-detection:dev": "npm run dev -w @google-psat/library-detection",
"design-system:prebuild": "npm run build:remove -w @google-psat/design-system",
"design-system:build": "npm run design-system:prebuild && npm run build -w @google-psat/design-system",
"design-system:dev": "npm run dev -w @google-psat/design-system",
"library-detection:prebuild": "npm run build:remove -w @google-psat/library-detection",
"library-detection:build": "npm run library-detection:prebuild && npm run build -w @google-psat/library-detection",
"library-detection:dev": "npm run dev -w @google-psat/library-detection",
"analysis-utils:prebuild": "npm run build:remove -w @google-psat/analysis-utils",
"analysis-utils:dev": "npm run dev -w @google-psat/analysis-utils",
"analysis-utils:build": "npm run analysis-utils:prebuild && npm run build -w @google-psat/analysis-utils",
"cli:predev": "npm run dev -w @google-psat/cli",
"cli:dev": "run-p tsc-packages:dev cli:predev",
"cli:prebuild": "npm run build:remove -w @google-psat/cli",
"cli:build": "cross-env NODE_ENV=production npm run build -w @google-psat/cli",
"build:cli": "npm run tsc-packages:build && npm run cli:prebuild && cross-env NODE_ENV=production npm run build -w @google-psat/cli",
"build-cli": "npm run build:cli && npm run cli-dashboard:build",
"cli:start": "npm install && npm run cli:dev",
"cli": "node packages/cli/dist/main.js",
"report:dev": "npm run dev -w @google-psat/report",
Expand All @@ -41,7 +41,7 @@
"ext:predev":"npm run dev -w @google-psat/extension",
"ext:dev": "run-p tsc-packages:dev ext:predev",
"ext:prebuild": "npm run build:remove -w @google-psat/extension",
"ext:build": "npm run tsc-packages:build && npm run ext:prebuild && cross-env NODE_ENV=production npm run build -w @google-psat/extension",
"build:ext": "npm run tsc-packages:build && npm run ext:prebuild && cross-env NODE_ENV=production npm run build -w @google-psat/extension",
"ext:start": "npm install && npm run ext:dev",
"lint": "npm-run-all --parallel lint:*",
"lint:js": "eslint .",
Expand Down
31 changes: 16 additions & 15 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,33 +72,34 @@ program
isFromNPMRegistry ? '[website-url] [option]' : '[website-url] -- [options]'
)
.description('CLI to test a URL for 3p cookies.')
.option(
'-u, --url <url>',
'The URL of a single site to analyze',
urlValidator
.argument('[website-url]', 'The URL of a single site to analyze', (value) =>
urlValidator(value, '[website-url]')
)
.option('-u, --url <url>', 'The URL of a single site to analyze', (value) =>
urlValidator(value, '-u')
)
.option(
'-s, --source-url <url>',
'The URL of a sitemap or CSV to analyze',
urlValidator
(value) => urlValidator(value, '-s')
)
.option(
'-f, --file <path>',
'The path to a local file (CSV or XML sitemap) to analyze',
filePathValidator
(value) => filePathValidator(value, '-f')
)
.option(
'-n, --number-of-urls <num>',
'Limit the number of URLs to analyze (from sitemap or CSV)',
numericValidator
(value) => numericValidator(value, '-n')
)
.option('-d, --display', 'Flag for running CLI in non-headless mode', false)
.option('-v, --verbose', 'Enables verbose logging', false)
.option('-t, --tech', 'Enables technology analysis', false)
.option(
'-o, --out-dir <path>',
'Directory to store analysis data (JSON, CSV, HTML) without launching the dashboard',
outDirValidator
(value) => outDirValidator(value, '-o')
)
.option(
'-i, --ignore-gdpr',
Expand All @@ -109,19 +110,19 @@ program
.option(
'-c, --concurrency <num>',
'Number of tabs to open in parallel during sitemap or CSV analysis',
numericValidator,
(value) => numericValidator(value, '-c'),
3
)
.option(
'-w, --wait <num>',
'Number of seconds to wait after the page is loaded before generating the report',
numericValidator,
20
'Number of milliseconds to wait after the page is loaded before generating the report',
(value) => numericValidator(value, '-w'),
20000
)
.option(
'-l, --locale <language>',
'Locale to use for the CLI, supported: en, hi, es, ja, ko, pt-BR',
localeValidator,
(value) => localeValidator(value, '-l'),
'en'
)
.helpOption('-h, --help', 'Display help for command')
Expand Down Expand Up @@ -155,7 +156,7 @@ program.parse();
const outDir = program.opts().outDir;
const shouldSkipAcceptBanner = program.opts().ignoreGdpr;
const concurrency = program.opts().concurrency;
const waitTime = program.opts().wait * 1000;
const waitTime = program.opts().wait;

const numArgs: number = [
Boolean(url),
Expand All @@ -166,7 +167,7 @@ program.parse();
return acc;
}, 0);

if (numArgs !== 1) {
if (numArgs > 1) {
console.error(
`Please provide one and only one of the following
a) URL of a site (-u or --url or default argument)
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/utils/coloredLoggers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ import chalk from 'chalk';

export const redLogger = (message: string) => {
console.log(chalk.red(message));
process.exit(1);
};
109 changes: 75 additions & 34 deletions packages/cli/src/utils/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
import { parseUrl } from '@google-psat/common';
import { existsSync, mkdirSync } from 'fs';
import path from 'path';
import { InvalidArgumentError } from 'commander';

/**
* Internal dependencies.
*/
import { redLogger } from './coloredLoggers';
import { LONG_CONSTANTS, SHORT_CONSTANTS } from './constants';
import { redLogger } from './coloredLoggers';

/**
* This will check if the argument for the flag is another flag.
Expand All @@ -49,103 +50,143 @@ function isOtherFlagsAsArgumentValidator(argument: string) {
/**
* This validates the waitTime or the concurrency of the URLs to be analysed together.
* @param {string} value The supposed numeric value.
* @param {string} flag The flag that the validator is validating.
* @returns The user passed value else default value.
*/
export function numericValidator(value: string) {
export function numericValidator(value: string, flag: string) {
if (isOtherFlagsAsArgumentValidator(value)) {
redLogger(
`Error: Please provide an argument for the flag as it cannot be empty.`
);
process.exit(1);
switch (flag) {
case '-n':
throw new InvalidArgumentError(
"Correct value for option '-n, --number-of-urls <num>' would be non negative number greater than 0 and less than equal to total number of urls"
);
case '-c':
throw new InvalidArgumentError(
"Correct value for option '-c, --concurrency <num>' would be non negative number greater than 0 and less than equal to total number of urls"
);
case '-w':
throw new InvalidArgumentError(
"Correct value for option '-w, --wait <num>' would be number of milliseconds greater than 0"
);
default:
throw new InvalidArgumentError('');
}
}

const parsedValue = parseInt(value);
if (isNaN(parsedValue)) {
redLogger(`${value} is not valid numeric value.`);
process.exit(1);
redLogger(`Error: ${value} is not valid numeric value.`);
}
return parsedValue;
}

/**
* This validates the locale provided by the user.
* @param {string} locale The locale provided by the user.
* @param {string} flag The flag that the validator is validating.
* @returns validated locale.
*/
export function localeValidator(locale: string) {
export function localeValidator(locale: string, flag: string) {
const availableLocales = ['en [default]', 'hi', 'es', 'ja', 'ko', 'pt-BR'];

if (isOtherFlagsAsArgumentValidator(locale)) {
redLogger(
`Error: Please provide an argument for the flag as it cannot be empty.`
);
process.exit(1);
switch (flag) {
case '-l':
throw new InvalidArgumentError(
`Correct value for option '-l, --locale <language>' would be ${availableLocales.join(
', '
)}`
);
default:
throw new InvalidArgumentError('');
}
}

const availableLocales = ['en [default]', 'hi', 'es', 'ja', 'ko', 'pt-BR'];
if (locale && !availableLocales.includes(locale)) {
redLogger(
`Locale '${locale}' is not supported, please use ${availableLocales.join(
`Error: Locale '${locale}' is not supported, please use ${availableLocales.join(
', '
)}.`
);
process.exit(1);
}
return locale;
}

/**
* This validates the file path to be analysed by the user.
* @param {string} filePath The file path provided by the user.
* @param {string} flag The flag that the validator is validating.
* @returns validated file path.
*/
export function filePathValidator(filePath: string) {
export function filePathValidator(filePath: string, flag: string) {
if (isOtherFlagsAsArgumentValidator(filePath)) {
redLogger(
`Error: Please provide an argument for the flag as it cannot be empty.`
);
process.exit(1);
switch (flag) {
case '-f':
throw new InvalidArgumentError(
"Correct value for option '-f, --file <path>' would be /users/path/to/urls.csv or /users/path/to/urls.xml"
);
default:
throw new InvalidArgumentError('');
}
}

const csvFileExists = existsSync(filePath);
if (!csvFileExists) {
redLogger(`Error: No file at ${filePath}`);
process.exit(1);
}
return filePath;
}

/**
* This validates the url to be analysed by the user.
* @param {string} url The url provided by the user.
* @param {string} flag The flag that the validator is validating.
* @returns validated url.
*/
export function urlValidator(url: string) {
export function urlValidator(url: string, flag: string) {
if (isOtherFlagsAsArgumentValidator(url)) {
redLogger(
`Error: Please provide an argument for the flag as it cannot be empty.`
);
process.exit(1);
switch (flag) {
case '[website-url]':
throw new InvalidArgumentError(
'Correct value for command-argument would be https://example.com'
);
case '-u':
throw new InvalidArgumentError(
"Correct value for option '-u, --url <url>' would be https://example.com"
);
case '-s':
throw new InvalidArgumentError(
"Correct value for option '-s, --source-url <url>' would be https://gagan.pro/sitemap/toypta.xml or https://sitemap.superintegratedapp.com/sitemaps/sitemap.csv"
);
default:
throw new InvalidArgumentError('');
}
}

const parsedUrl = parseUrl(url);

if (parsedUrl === null) {
redLogger(`Error: Invalid Url ${parsedUrl}`);
process.exit(1);
redLogger(`Error: Invalid Url ${url}`);
}
return url;
}

/**
* This validates the output directory path provided by the user.
* @param {string} outDir output directory path provided by the user.
* @param {string} flag The flag that the validator is validating.
* @returns validated outDir or the created output directory.
*/
export function outDirValidator(outDir: string) {
export function outDirValidator(outDir: string, flag: string) {
if (isOtherFlagsAsArgumentValidator(outDir)) {
redLogger(
`Error: Please provide an argument for the flag as it cannot be empty.`
);
process.exit(1);
switch (flag) {
case '-o':
throw new InvalidArgumentError(
"Correct value for option '-o, --out-dir <path>' would be /users/path/to/save/output"
);
default:
throw new InvalidArgumentError('');
}
}

const parentDirExists = existsSync(path.resolve('./out'));
Expand Down

0 comments on commit cc98d10

Please sign in to comment.