create-rx-app
Version:
ReactXP Project Generator
265 lines (264 loc) • 14.6 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Generator = void 0;
var mustache_1 = __importDefault(require("mustache"));
var username_1 = __importDefault(require("username"));
var chalk_1 = __importDefault(require("chalk"));
var uuid_1 = require("uuid");
var path_1 = __importDefault(require("path"));
var fs_extra_1 = __importDefault(require("fs-extra"));
var os_1 = __importDefault(require("os"));
var lodash_1 = require("lodash");
var child_process_1 = require("child_process");
var package_manager_1 = require("./package-manager");
var utils_1 = require("./utils");
var TYPESCRIPT_FOLDER = 'typescript';
var JAVASCRIPT_FOLDER = 'javascript';
var WINDOWS_FOLDER = 'windows';
var COMMON_FOLDER = 'common';
var IOS_FOLDER = 'ios';
var TEMP_PACKAGE_JSON = '_package.json';
var NPM_INSTALL = 'npm i';
var NPM_RUN = 'npm run';
var YARN = 'yarn';
var TEMPLATE_PATH = path_1.default.resolve(__dirname, '..', 'template');
var COMMON_TEMPLATE_PATH = path_1.default.join(TEMPLATE_PATH, COMMON_FOLDER);
var WINDOWS_TEMPLATE_PATH = path_1.default.join(COMMON_TEMPLATE_PATH, WINDOWS_FOLDER);
var WINDOWS_TEMPORARY_KEY_PATH = path_1.default.join(WINDOWS_TEMPLATE_PATH, 'ProjectName', 'ProjectName_TemporaryKey.pfx');
var JEST_TEMPLATE_PATH = path_1.default.join(COMMON_TEMPLATE_PATH, 'jest');
var chdir = process.chdir;
var Generator = /** @class */ (function () {
function Generator(options) {
this.packageJson = {};
this.params = {};
var projectName = options.projectName, javascript = options.javascript, yarn = options.yarn;
this.params = {
ProjectName: projectName,
displayName: projectName,
projectname: projectName.toLowerCase(),
};
this.templateFolderName = javascript
? JAVASCRIPT_FOLDER
: TYPESCRIPT_FOLDER;
this.runCommand = yarn ? YARN : NPM_RUN;
this.options = options;
}
Generator.prototype.run = function () {
var _a = this.options, projectPath = _a.projectPath, skipInstall = _a.skipInstall;
console.log(chalk_1.default.white.bold('Setting up new ReactXP app in %s'), projectPath);
if (!fs_extra_1.default.existsSync(projectPath)) {
fs_extra_1.default.mkdirSync(projectPath);
}
this.setPackageJson();
this.generatePackageJson();
if (!skipInstall) {
this.installDependencies();
}
this.generateApp();
this.generateWindowsApp();
this.printInstructions();
};
Generator.prototype.generateApp = function () {
var _this = this;
var _a = this.options, skipJest = _a.skipJest, javascript = _a.javascript;
var templatePaths = [
COMMON_TEMPLATE_PATH,
path_1.default.join(TEMPLATE_PATH, this.templateFolderName),
];
var excludePaths = [WINDOWS_TEMPLATE_PATH, TEMP_PACKAGE_JSON];
if (skipJest) {
excludePaths.push(JEST_TEMPLATE_PATH);
excludePaths.push("App.spec." + (javascript ? 'js' : 'tsx'));
}
var pathParams = __assign(__assign({}, this.params), { '_metro.config.js': 'metro.config.js', '_babel.config.js': 'babel.config.js', _eslintrc: '.eslintrc', _gitignore: '.gitignore', '_tsconfig.json': 'tsconfig.json', '_tslint.json': 'tslint.json', '_README.md': 'README.md' });
var contnetParams = __assign(__assign({}, this.params), { runCommand: this.runCommand, version: utils_1.getVersion(), skipJest: skipJest });
templatePaths.forEach(function (srcPath) {
return _this.walk(srcPath, excludePaths).forEach(function (absolutePath) {
return _this.copy(absolutePath, _this.buildDestPath(absolutePath, srcPath, pathParams), contnetParams);
});
});
};
Generator.prototype.generateWindowsApp = function () {
var _this = this;
var currentUser = username_1.default.sync();
var certificateThumbprint = this.buildSelfSignedCertificate(currentUser);
var contnetParams = __assign(__assign(__assign({}, this.params), (certificateThumbprint && { certificateThumbprint: certificateThumbprint })), { currentUser: currentUser, packageGuid: uuid_1.v4(), projectGuid: uuid_1.v4() });
var pathParams = __assign(__assign({}, this.params), { _gitignore: '.gitignore' });
var excludePaths = certificateThumbprint
? [WINDOWS_TEMPORARY_KEY_PATH]
: [];
this.walk(WINDOWS_TEMPLATE_PATH, excludePaths).forEach(function (absolutePath) {
return _this.copy(absolutePath, _this.buildDestPath(absolutePath, COMMON_TEMPLATE_PATH, pathParams), contnetParams);
});
};
Generator.prototype.buildSelfSignedCertificate = function (currentUser) {
var _a = this.options, projectPath = _a.projectPath, projectName = _a.projectName;
if (os_1.default.platform() !== 'win32') {
return '';
}
console.log('%s %s', chalk_1.default.blue.bold('[windows]'), chalk_1.default.white.bold('Generating self-signed certificate...'));
var certificateDestPath = path_1.default.join(projectPath, WINDOWS_FOLDER, projectName);
var certificateFileDestPath = path_1.default.join(certificateDestPath, projectName);
var certificateArgs = [
[
'$cert = New-SelfSignedCertificate -KeyUsage DigitalSignature -KeyExportPolicy Exportable -Subject',
"\"CN=" + currentUser + "\" -TextExtension @(\"2.5.29.37={text}1.3.6.1.5.5.7.3.3\", \"2.5.29.19={text}Subject Type:End Entity\")",
"-CertStoreLocation \"Cert:\\CurrentUser\\My\"",
].join(' '),
'$pwd = ConvertTo-SecureString -String password -Force -AsPlainText',
"New-Item -ErrorAction Ignore -ItemType directory -Path " + certificateDestPath,
[
"Export-PfxCertificate -Cert \"cert:\\CurrentUser\\My\\$($cert.Thumbprint)\"",
"-FilePath " + certificateFileDestPath + "_TemporaryKey.pfx -Password $pwd",
].join(' '),
'$cert.Thumbprint',
].join(';');
if (!fs_extra_1.default.existsSync(certificateDestPath)) {
fs_extra_1.default.mkdirpSync(certificateDestPath);
}
var _b = child_process_1.spawnSync('powershell', [
'-command',
certificateArgs,
]), status = _b.status, stdout = _b.stdout;
if (status === 0) {
console.log('%s %s', chalk_1.default.blue.bold('[windows]'), chalk_1.default.green.bold('Self-signed certificate generated successfully.'));
var output = stdout.toString().trim().split('\n');
return output[output.length - 1];
}
console.log('%s %s', chalk_1.default.blue.bold('[windows]'), chalk_1.default.red.bold('Failed to generate Self-signed certificate.'));
console.log('%s %s', chalk_1.default.blue.bold('[windows]'), chalk_1.default.yellow.bold('Using Default Certificate. Use Visual Studio to renew it.'));
return '';
};
Generator.prototype.generatePackageJson = function () {
var _a = this.options, projectPath = _a.projectPath, projectName = _a.projectName, skipInstall = _a.skipInstall;
var packageJson = JSON.stringify(__assign({ name: projectName.toLowerCase() }, lodash_1.omit(this.packageJson, skipInstall ? [] : ['devDependencies', 'dependencies'])), null, 2);
fs_extra_1.default.writeFileSync(path_1.default.resolve(projectPath, 'package.json'), packageJson);
};
Generator.prototype.printInstructions = function () {
var _a = this.options, projectName = _a.projectName, projectPath = _a.projectPath, skipInstall = _a.skipInstall, yarn = _a.yarn;
var xcodeProjectPath = path_1.default.resolve(projectPath, IOS_FOLDER, projectName) + ".xcodeproj";
var windowsProjectPath = path_1.default.resolve(projectPath, WINDOWS_FOLDER, projectName) + ".sln";
console.log(chalk_1.default.green.bold('%s was successfully created. \n'), projectName);
if (skipInstall) {
console.log(chalk_1.default.green.bold('To install dependencies:'));
console.log(' cd %s', projectPath);
console.log(chalk_1.default.white.bold(' %s \n'), yarn ? YARN : NPM_INSTALL);
}
console.log(chalk_1.default.yellow.bold('To run your app on Web:'));
console.log(' cd %s', projectPath);
console.log(chalk_1.default.white.bold(' %s start:web \n'), this.runCommand);
console.log(chalk_1.default.yellow.bold('To build Web production version of your app:'));
console.log(' cd %s', projectPath);
console.log(chalk_1.default.white.bold(' %s build:web \n'), this.runCommand);
console.log(chalk_1.default.cyan.bold('To run your app on iOS:'));
console.log(' cd %s', projectPath);
console.log(chalk_1.default.white.bold(' %s start:ios'), this.runCommand);
console.log(' - or -');
console.log(' open %s project in Xcode', path_1.default.relative(projectPath, xcodeProjectPath));
console.log(' press the Run button \n');
console.log(chalk_1.default.green.bold('To run your app on Android:'));
console.log(' cd %s', projectPath);
console.log(' Have an Android emulator running (quickest way to get started), or a device connected.');
console.log(chalk_1.default.white.bold(' %s start:android'), this.runCommand);
console.log(' - or -');
console.log(chalk_1.default.white.bold(' open android/ project in Android Studio'));
console.log(' press the Run button \n');
console.log(chalk_1.default.blue.bold('To run your app on Windows:'));
console.log(' cd %s', projectPath);
console.log(chalk_1.default.white.bold(' %s start:windows'), this.runCommand);
console.log(' - or -');
console.log(chalk_1.default.white.bold(' open %s project in Visual Studio'), windowsProjectPath);
console.log(' press the Run button \n');
};
Generator.prototype.installDependencies = function () {
var _a = this.packageJson, devDependencies = _a.devDependencies, dependencies = _a.dependencies;
var _b = this.options, projectPath = _b.projectPath, yarn = _b.yarn;
var packageManager = new package_manager_1.PackageManager(yarn);
chdir(projectPath);
packageManager.install(devDependencies, 'dev dependencies', true);
packageManager.install(dependencies, 'dependencies');
};
Generator.prototype.setPackageJson = function () {
var packageJson = lodash_1.merge(this.buildPackageJson(COMMON_FOLDER), this.buildPackageJson(this.templateFolderName));
this.packageJson = __assign(__assign({}, packageJson), { devDependencies: utils_1.sortKeys(packageJson.devDependencies), dependencies: utils_1.sortKeys(packageJson.dependencies) });
};
Generator.prototype.buildPackageJson = function (srcFolder) {
var _a = this.options, skipJest = _a.skipJest, yarn = _a.yarn;
var content = fs_extra_1.default.readFileSync(path_1.default.join(TEMPLATE_PATH, srcFolder, TEMP_PACKAGE_JSON), { encoding: 'utf8' });
var params = {
paramsPrefix: yarn ? ' ' : ' -- ',
runCommand: this.runCommand,
skipJest: skipJest,
};
return JSON.parse(mustache_1.default.render(content, params, {}, ['<%', '%>']));
};
Generator.prototype.buildDestPath = function (absolutePath, relativeTo, params) {
var destPath = path_1.default.resolve(this.options.projectPath, path_1.default.relative(relativeTo, absolutePath));
Object.keys(params).forEach(function (regexp) {
return (destPath = destPath.replace(new RegExp("\\b" + regexp, 'g'), params[regexp]));
});
return destPath;
};
Generator.prototype.copy = function (srcPath, destPath, params) {
if (fs_extra_1.default.lstatSync(srcPath).isDirectory()) {
if (!fs_extra_1.default.existsSync(destPath)) {
fs_extra_1.default.mkdirSync(destPath);
}
return;
}
else {
if (this.isBinary(srcPath)) {
fs_extra_1.default.copyFileSync(srcPath, destPath);
}
else {
var permissions = fs_extra_1.default.statSync(srcPath).mode;
var content = mustache_1.default.render(fs_extra_1.default.readFileSync(srcPath, 'utf8'), params, {}, ['<%', '%>']);
fs_extra_1.default.writeFileSync(destPath, content, {
encoding: 'utf8',
mode: permissions,
});
}
}
};
Generator.prototype.isBinary = function (srcPath) {
return (['.png', '.jpg', '.jar', '.ico', '.pfx', '.keystore'].indexOf(path_1.default.extname(srcPath)) >= 0);
};
Generator.prototype.walk = function (srcPath, excludePaths) {
var _this = this;
if (excludePaths === void 0) { excludePaths = []; }
var isExcluded = function (file) {
return excludePaths.some(function (p) { return file.indexOf(p) >= 0; });
};
if (!fs_extra_1.default.lstatSync(srcPath).isDirectory()) {
return isExcluded(srcPath) ? [] : [srcPath];
}
return __spreadArrays([
srcPath
], lodash_1.flatten(fs_extra_1.default
.readdirSync(srcPath)
.map(function (child) { return _this.walk(path_1.default.join(srcPath, child)); }))).filter(function (absolutePath) { return !isExcluded(absolutePath); });
};
return Generator;
}());
exports.Generator = Generator;