🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more →

@revolut/web-cli

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@revolut/web-cli - npm Package Compare versions

Comparing version

to
1.5.0

{
"name": "@revolut/web-cli",
"version": "1.4.2",
"version": "1.5.0",
"license": "Apache-2.0",

@@ -5,0 +5,0 @@ "description": "Interactive CLI tool for web projects to provide automation for various tasks",

export declare type TemplateName = 'app' | 'backoffice-library' | 'backoffice-microfrontend' | 'backoffice-app' | 'library';
export declare const TEMPLATES: TemplateName[];
export declare const TEMPLATE_FILES_MAPPING: Record<TemplateName, string[]>;
export declare enum TemplateKind {
WebApp = "WebApp",
Infrastructure = "Infrastructure"
}
export declare const TEMPLATE_DIR: Record<TemplateKind, string>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TEMPLATE_FILES_MAPPING = exports.TEMPLATES = void 0;
exports.TEMPLATE_DIR = exports.TemplateKind = exports.TEMPLATE_FILES_MAPPING = exports.TEMPLATES = void 0;
exports.TEMPLATES = [

@@ -25,2 +25,11 @@ 'app',

};
var TemplateKind;
(function (TemplateKind) {
TemplateKind["WebApp"] = "WebApp";
TemplateKind["Infrastructure"] = "Infrastructure";
})(TemplateKind = exports.TemplateKind || (exports.TemplateKind = {}));
exports.TEMPLATE_DIR = {
[TemplateKind.WebApp]: 'web-app',
[TemplateKind.Infrastructure]: 'infrastructure',
};
//# sourceMappingURL=constants.js.map
export * from './constants';
export * from './RushConfigDataMiner';
export * from './utils/RushConfigDataMiner';

@@ -18,3 +18,3 @@ "use strict";

__exportStar(require("./constants"), exports);
__exportStar(require("./RushConfigDataMiner"), exports);
__exportStar(require("./utils/RushConfigDataMiner"), exports);
//# sourceMappingURL=exports-for-tests.js.map
#!/usr/bin/env node
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -32,30 +9,10 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

const update_notifier_1 = __importDefault(require("update-notifier"));
const enquirer_1 = require("enquirer");
const chalk_1 = require("chalk");
const ora_1 = __importDefault(require("ora"));
const fs_jetpack_1 = __importDefault(require("fs-jetpack"));
const package_json_1 = __importDefault(require("../package.json"));
const actions_1 = require("./actions");
const constants_1 = require("./constants");
const RushConfigDataMiner_1 = require("./RushConfigDataMiner");
const RushConfigEditor_1 = require("./RushConfigEditor");
const utils_1 = require("./utils");
(0, update_notifier_1.default)({ pkg: package_json_1.default }).notify();
const program = new commander_1.Command();
program.version(package_json_1.default.version);
const callerDirCwd = fs_jetpack_1.default.cwd();
const webCliCwd = fs_jetpack_1.default.cwd(__dirname, '..');
function getUnscopedPackageName(packageName) {
return packageName.includes('@') ? packageName.split('/')[1] : packageName;
}
function getDefaultAppFolder(template, packageName) {
const unscopedPackageName = getUnscopedPackageName(packageName);
switch (template) {
case 'backoffice-app':
return `backoffice-ui-apps/${unscopedPackageName}`;
case 'backoffice-library':
return `packages/${unscopedPackageName}`;
default:
return `${unscopedPackageName}`;
}
}
// Scaffold web app
program

@@ -77,119 +34,13 @@ .command('scaffold')

})
.action(async (options) => {
var _a, _b;
// Read inputs and ask to provide if not provided
const { template } = await (0, enquirer_1.prompt)({
name: 'template',
message: 'Select template.',
type: 'select',
choices: constants_1.TEMPLATES,
initial: options.template,
skip: Boolean(options.template),
});
const { packageName } = await (0, enquirer_1.prompt)({
name: 'packageName',
message: 'Name of the package',
type: 'input',
initial: options.packageName || '@revolut/',
skip: Boolean(options.packageName),
});
const { folderName } = await (0, enquirer_1.prompt)({
name: 'folderName',
message: 'Name of the destination folder',
type: 'input',
initial: options.folderName || getDefaultAppFolder(template, packageName),
skip: Boolean(options.folderName),
});
const { publicUrl } = await (0, enquirer_1.prompt)({
name: 'publicUrl',
message: 'Application PUBLIC_URL',
type: 'input',
initial: options.publicUrl ||
`${template === 'backoffice-microfrontend' ? '/microfrontends' : ''}/${getUnscopedPackageName(packageName)}`,
validate: (value) => {
const requiredPrefix = template === 'backoffice-microfrontend' ? '/microfrontends/' : '/';
if (!value.startsWith(requiredPrefix)) {
return `Should start with ${requiredPrefix}`;
}
return true;
},
skip: Boolean(options.publicUrl) ||
!(constants_1.TEMPLATE_FILES_MAPPING[template] &&
constants_1.TEMPLATE_FILES_MAPPING[template].includes('.env.production')),
});
const copyTemplateSpinner = (0, ora_1.default)('Copy template to selected folder').start();
const templateDir = `${webCliCwd.cwd()}/templates/${template}`;
try {
fs_jetpack_1.default.copy(templateDir, `${callerDirCwd}/${folderName}`);
copyTemplateSpinner.succeed();
}
catch (e) {
copyTemplateSpinner.fail();
console.error((0, chalk_1.redBright)('Folder already exists, please, try again with different folder name.'));
console.error();
console.error((0, chalk_1.cyan)('Copy command below to save some typing:'));
console.error((0, chalk_1.green)(`revolut-web-cli scaffold -pn ${packageName} -t ${template}`));
console.error();
console.error();
console.error((0, chalk_1.redBright)('Original error:'));
console.error(e);
process.exit(1);
}
const fillingTemplatesSpinner = (0, ora_1.default)('Replacing placeholders in template files').start();
const scaffoldedProjectRootCwd = fs_jetpack_1.default.cwd(folderName);
const templateFilesDirsToReadAndOverwrite = constants_1.TEMPLATE_FILES_MAPPING[template];
templateFilesDirsToReadAndOverwrite.forEach((templateFileDir) => {
const templateFile = scaffoldedProjectRootCwd.read(templateFileDir);
if (!templateFile) {
fillingTemplatesSpinner.fail();
console.error((0, chalk_1.redBright)('Cannot find template file!'));
process.exit(1);
return;
}
const changed = templateFile
.replace('{packageName}', packageName)
.replace('{publicUrl}', publicUrl);
scaffoldedProjectRootCwd.write(templateFileDir, changed);
});
fillingTemplatesSpinner.succeed();
const isRushRepo = !options.ignoreRush && (0, utils_1.isRushManagedRepo)();
if (isRushRepo) {
const { RushConfiguration } = await Promise.resolve().then(() => __importStar(require('@microsoft/rush-lib')));
RushConfiguration.tryFindRushJsonLocation({
startingFolder: process.cwd(),
});
const rushConfig = RushConfiguration.loadFromDefaultLocation({
startingFolder: process.cwd(),
});
const rushDataMinerService = RushConfigDataMiner_1.RushConfigDataMiner.getInstance(rushConfig);
const allNonPeerMonorepoDependencies = rushDataMinerService.getAllNonPeerDependencies();
// If it's needed we ensure we have consistent versions with Rush monorepo in this new package.json
if (rushConfig.ensureConsistentVersions) {
const ensureRushConsistentVersionsSpinner = (0, ora_1.default)('Ensure rush.js consistent versions are set').start();
const scaffoldedProjectPackageJson = JSON.parse(scaffoldedProjectRootCwd.read('package.json'));
scaffoldedProjectPackageJson.dependencies = (0, utils_1.alignDependenciesWithMonorepoVersions)((_a = scaffoldedProjectPackageJson.dependencies) !== null && _a !== void 0 ? _a : {}, allNonPeerMonorepoDependencies);
scaffoldedProjectPackageJson.devDependencies =
(0, utils_1.alignDependenciesWithMonorepoVersions)((_b = scaffoldedProjectPackageJson.devDependencies) !== null && _b !== void 0 ? _b : {}, allNonPeerMonorepoDependencies);
scaffoldedProjectRootCwd.write('package.json', JSON.stringify(scaffoldedProjectPackageJson, null, 2));
ensureRushConsistentVersionsSpinner.succeed();
}
const addingPackageToRushJson = (0, ora_1.default)('Adding package to rush.json').start();
const rushConfigEditor = RushConfigEditor_1.RushConfigEditor.getInstance(rushConfig);
const scaffoldedProjectFolderAbsoluteToRoot = scaffoldedProjectRootCwd
.cwd()
.split(`${rushConfig.rushJsonFolder}/`)[1];
const project = {
packageName,
projectFolder: scaffoldedProjectFolderAbsoluteToRoot,
shouldPublish: false,
cyclicDependencyProjects: [],
};
template === 'backoffice-library' && (project.versionPolicyName = 'library');
rushConfigEditor.addProject(project);
rushConfigEditor.saveIfModified();
addingPackageToRushJson.succeed();
}
console.log((0, chalk_1.green)('🛠 Scaffold successful!'));
});
.action(actions_1.scaffoldWebAppAction);
// Scaffold infra
program
.command('scaffold-infra')
.description('Scaffold infrastructure configs for web app')
.usage('--app-name my-app --app-domain my-app.revolut.com')
.option('-an, --app-name <name>', 'Application name')
.option('-ad, --app-domain <domain>', 'Application side domain name')
.option('-sr, --sentry-report-uri [url]', 'Sentry CSP report-uri url (see https://docs.sentry.io/product/security-policy-reporting/#content-security-policy for more details)')
.action(actions_1.scaffoldInfrastructureAction);
program.parse(process.argv);
//# sourceMappingURL=index.js.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const rush_lib_1 = require("@microsoft/rush-lib");
const RushConfigDataMiner_1 = require("../RushConfigDataMiner");
const RushConfigEditor_1 = require("../RushConfigEditor");
const utils_1 = require("../utils");
const rushConfig = rush_lib_1.RushConfiguration.loadFromConfigurationFile('./resources/rush.json');
describe('RushConfigDataMiner', () => {
it('Returns same instance for the same config', () => {
const dataMiner1 = RushConfigDataMiner_1.RushConfigDataMiner.getInstance(rushConfig);
const dataMiner2 = RushConfigDataMiner_1.RushConfigDataMiner.getInstance(rushConfig);
const dataMiner1 = utils_1.RushConfigDataMiner.getInstance(rushConfig);
const dataMiner2 = utils_1.RushConfigDataMiner.getInstance(rushConfig);
expect(dataMiner1).toBe(dataMiner2);

@@ -16,4 +15,4 @@ });

it('Returns same instance for the same config', () => {
const dataEditor1 = RushConfigEditor_1.RushConfigEditor.getInstance(rushConfig);
const dataEditor2 = RushConfigEditor_1.RushConfigEditor.getInstance(rushConfig);
const dataEditor1 = utils_1.RushConfigEditor.getInstance(rushConfig);
const dataEditor2 = utils_1.RushConfigEditor.getInstance(rushConfig);
expect(dataEditor1).toBe(dataEditor2);

@@ -20,0 +19,0 @@ });

{
"name": "@revolut/web-cli",
"version": "1.4.2",
"version": "1.5.0",
"license": "Apache-2.0",

@@ -5,0 +5,0 @@ "description": "Interactive CLI tool for web projects to provide automation for various tasks",

@@ -9,3 +9,3 @@ export type TemplateName =

export const TEMPLATES: TemplateName[] = [
'app', // TBD
'app',
'backoffice-library',

@@ -32,1 +32,11 @@ 'backoffice-microfrontend',

}
export enum TemplateKind {
WebApp = 'WebApp',
Infrastructure = 'Infrastructure',
}
export const TEMPLATE_DIR: Record<TemplateKind, string> = {
[TemplateKind.WebApp]: 'web-app',
[TemplateKind.Infrastructure]: 'infrastructure',
}
export * from './constants'
export * from './RushConfigDataMiner'
export * from './utils/RushConfigDataMiner'
#!/usr/bin/env node
import { Command } from 'commander'
import updateNotifier from 'update-notifier'
import { prompt } from 'enquirer'
import { cyan, green, redBright, yellow } from 'chalk'
import ora from 'ora'
import jetpack from 'fs-jetpack'
import type { IRushConfigurationProjectJson } from '@microsoft/rush-lib/lib/api/RushConfigurationProject'
import { green, redBright, yellow } from 'chalk'
import pkg from '../package.json'
import { TEMPLATE_FILES_MAPPING, TEMPLATES, TemplateName } from './constants'
import { RushConfigDataMiner } from './RushConfigDataMiner'
import { RushConfigEditor } from './RushConfigEditor'
import { alignDependenciesWithMonorepoVersions, isRushManagedRepo } from './utils'
import { scaffoldInfrastructureAction, scaffoldWebAppAction } from './actions'
import { TEMPLATES, TemplateName } from './constants'
type ScaffoldOptions = {
folderName: string
packageName: string
publicUrl?: string
template: TemplateName
ignoreRush: boolean
}
updateNotifier({ pkg }).notify()
interface ScaffoldProgram extends Command, Partial<ScaffoldOptions> {}
const program = new Command()
program.version(pkg.version)
const callerDirCwd = jetpack.cwd()
const webCliCwd = jetpack.cwd(__dirname, '..')
function getUnscopedPackageName(packageName: string): string {
return packageName.includes('@') ? packageName.split('/')[1] : packageName
}
function getDefaultAppFolder(template: TemplateName, packageName: string) {
const unscopedPackageName = getUnscopedPackageName(packageName)
switch (template) {
case 'backoffice-app':
return `backoffice-ui-apps/${unscopedPackageName}`
case 'backoffice-library':
return `packages/${unscopedPackageName}`
default:
return `${unscopedPackageName}`
}
}
// Scaffold web app
program

@@ -75,147 +42,17 @@ .command('scaffold')

)
.action(async (options: ScaffoldProgram) => {
// Read inputs and ask to provide if not provided
const { template } = await prompt<{
template: TemplateName
}>({
name: 'template',
message: 'Select template.',
type: 'select',
choices: TEMPLATES,
initial: options.template as unknown as number,
skip: Boolean(options.template),
})
const { packageName } = await prompt<{ packageName: string }>({
name: 'packageName',
message: 'Name of the package',
type: 'input',
initial: options.packageName || '@revolut/',
skip: Boolean(options.packageName),
})
const { folderName } = await prompt<{ folderName: string }>({
name: 'folderName',
message: 'Name of the destination folder',
type: 'input',
initial: options.folderName || getDefaultAppFolder(template, packageName),
skip: Boolean(options.folderName),
})
const { publicUrl } = await prompt<{ publicUrl: string }>({
name: 'publicUrl',
message: 'Application PUBLIC_URL',
type: 'input',
initial:
options.publicUrl ||
`${
template === 'backoffice-microfrontend' ? '/microfrontends' : ''
}/${getUnscopedPackageName(packageName)}`,
validate: (value) => {
const requiredPrefix =
template === 'backoffice-microfrontend' ? '/microfrontends/' : '/'
if (!value.startsWith(requiredPrefix)) {
return `Should start with ${requiredPrefix}`
}
.action(scaffoldWebAppAction)
return true
},
skip:
Boolean(options.publicUrl) ||
!(
TEMPLATE_FILES_MAPPING[template] &&
TEMPLATE_FILES_MAPPING[template].includes('.env.production')
),
})
// Scaffold infra
program
.command('scaffold-infra')
.description('Scaffold infrastructure configs for web app')
.usage('--app-name my-app --app-domain my-app.revolut.com')
.option('-an, --app-name <name>', 'Application name')
.option('-ad, --app-domain <domain>', 'Application side domain name')
.option(
'-sr, --sentry-report-uri [url]',
'Sentry CSP report-uri url (see https://docs.sentry.io/product/security-policy-reporting/#content-security-policy for more details)',
)
.action(scaffoldInfrastructureAction)
const copyTemplateSpinner = ora('Copy template to selected folder').start()
const templateDir = `${webCliCwd.cwd()}/templates/${template}`
try {
jetpack.copy(templateDir, `${callerDirCwd}/${folderName}`)
copyTemplateSpinner.succeed()
} catch (e) {
copyTemplateSpinner.fail()
console.error(
redBright('Folder already exists, please, try again with different folder name.'),
)
console.error()
console.error(cyan('Copy command below to save some typing:'))
console.error(green(`revolut-web-cli scaffold -pn ${packageName} -t ${template}`))
console.error()
console.error()
console.error(redBright('Original error:'))
console.error(e)
process.exit(1)
}
const fillingTemplatesSpinner = ora(
'Replacing placeholders in template files',
).start()
const scaffoldedProjectRootCwd = jetpack.cwd(folderName)
const templateFilesDirsToReadAndOverwrite = TEMPLATE_FILES_MAPPING[template]
templateFilesDirsToReadAndOverwrite.forEach((templateFileDir) => {
const templateFile = scaffoldedProjectRootCwd.read(templateFileDir)
if (!templateFile) {
fillingTemplatesSpinner.fail()
console.error(redBright('Cannot find template file!'))
process.exit(1)
return
}
const changed = templateFile
.replace('{packageName}', packageName)
.replace('{publicUrl}', publicUrl)
scaffoldedProjectRootCwd.write(templateFileDir, changed)
})
fillingTemplatesSpinner.succeed()
const isRushRepo = !options.ignoreRush && isRushManagedRepo()
if (isRushRepo) {
const { RushConfiguration } = await import('@microsoft/rush-lib')
RushConfiguration.tryFindRushJsonLocation({
startingFolder: process.cwd(),
})
const rushConfig = RushConfiguration.loadFromDefaultLocation({
startingFolder: process.cwd(),
})
const rushDataMinerService = RushConfigDataMiner.getInstance(rushConfig)
const allNonPeerMonorepoDependencies =
rushDataMinerService.getAllNonPeerDependencies()
// If it's needed we ensure we have consistent versions with Rush monorepo in this new package.json
if (rushConfig.ensureConsistentVersions) {
const ensureRushConsistentVersionsSpinner = ora(
'Ensure rush.js consistent versions are set',
).start()
const scaffoldedProjectPackageJson = JSON.parse(
scaffoldedProjectRootCwd.read('package.json') as string,
)
scaffoldedProjectPackageJson.dependencies = alignDependenciesWithMonorepoVersions(
scaffoldedProjectPackageJson.dependencies ?? {},
allNonPeerMonorepoDependencies,
)
scaffoldedProjectPackageJson.devDependencies =
alignDependenciesWithMonorepoVersions(
scaffoldedProjectPackageJson.devDependencies ?? {},
allNonPeerMonorepoDependencies,
)
scaffoldedProjectRootCwd.write(
'package.json',
JSON.stringify(scaffoldedProjectPackageJson, null, 2),
)
ensureRushConsistentVersionsSpinner.succeed()
}
const addingPackageToRushJson = ora('Adding package to rush.json').start()
const rushConfigEditor = RushConfigEditor.getInstance(rushConfig)
const scaffoldedProjectFolderAbsoluteToRoot = scaffoldedProjectRootCwd
.cwd()
.split(`${rushConfig.rushJsonFolder}/`)[1]
const project: IRushConfigurationProjectJson = {
packageName,
projectFolder: scaffoldedProjectFolderAbsoluteToRoot,
shouldPublish: false,
cyclicDependencyProjects: [],
}
template === 'backoffice-library' && (project.versionPolicyName = 'library')
rushConfigEditor.addProject(project)
rushConfigEditor.saveIfModified()
addingPackageToRushJson.succeed()
}
console.log(green('🛠 Scaffold successful!'))
})
program.parse(process.argv)
import { RushConfiguration } from '@microsoft/rush-lib'
import { RushConfigDataMiner } from '../RushConfigDataMiner'
import { RushConfigEditor } from '../RushConfigEditor'
import { RushConfigEditor, RushConfigDataMiner } from '../utils'

@@ -5,0 +4,0 @@ const rushConfig = RushConfiguration.loadFromConfigurationFile('./resources/rush.json')

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet