@nstudio/schematics
Version:
Cross-platform (xplat) tools for Nx workspaces.
287 lines • 13.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const schematics_1 = require("@angular-devkit/schematics");
const utils_1 = require("../utils");
const ts = require("typescript");
const test_1 = require("@schematics/angular/utility/test");
const strings_1 = require("@angular-devkit/core/src/utils/strings");
let featureName;
let projectNames;
function default_1(options) {
if (!options.name) {
throw new schematics_1.SchematicsException(`You did not specify the name of the feature you'd like to generate. For example: ng g feature my-feature`);
}
featureName = options.name.toLowerCase();
let projects = options.projects;
let platforms = [];
if (options.adjustSandbox) {
// when adjusting sandbox for the feature, turn dependent options on
// for convenience also setup some default fallbacks to avoid requiring so many options
// sandbox flags are meant to be quick and convenient
options.onlyProject = true;
options.routing = true;
if (!projects) {
if (!options.platforms) {
// default to {N} sandbox
projects = 'nativescript-sandbox';
}
else {
platforms = options.platforms.split(",");
const projectSandboxNames = [];
// default to project with sandbox name
for (const p of platforms) {
if (utils_1.supportedSandboxPlatforms.includes(p)) {
projectSandboxNames.push(`${p}-sandbox`);
}
else {
throw new schematics_1.SchematicsException(`The --adjustSandbox flag supports the following at the moment: ${utils_1.supportedSandboxPlatforms}`);
}
}
projects = projectSandboxNames.join(',');
}
}
}
if (options.routing && !options.onlyProject) {
throw new schematics_1.SchematicsException(`When generating a feature with the --routing option, please also specify --onlyProject. Support for shared code routing is under development and will be available in the future.`);
}
if (projects) {
// building feature in shared code and in projects
projectNames = projects.split(",");
for (const name of projectNames) {
const platPrefix = name.split("-")[0];
if (utils_1.supportedPlatforms.includes(platPrefix) &&
!platforms.includes(platPrefix)) {
// if project name is prefixed with supported platform and not already added
platforms.push(platPrefix);
}
}
}
else if (options.platforms) {
// building feature in shared code only
platforms = options.platforms.split(",");
}
if (platforms.length === 0) {
let error = projects ? utils_1.platformAppPrefixError() : utils_1.generatorError("feature");
throw new schematics_1.SchematicsException(utils_1.optionsMissingError(error));
}
const targetPlatforms = {};
for (const t of platforms) {
if (utils_1.supportedPlatforms.includes(t)) {
targetPlatforms[t] = true;
}
else {
throw new schematics_1.SchematicsException(utils_1.unsupportedPlatformError(t));
}
}
const projectChains = [];
if (options.onlyProject) {
for (const projectName of projectNames) {
const platPrefix = projectName.split("-")[0];
let srcDir = platPrefix !== "nativescript" ? "src/" : "";
// check for 2 different naming conventions on routing modules
const routingModulePathOptions = [];
const appDirectory = `apps/${projectName}/${srcDir}app/`;
routingModulePathOptions.push(`${appDirectory}app.routing.ts`);
routingModulePathOptions.push(`${appDirectory}app-routing.module.ts`);
projectChains.push((tree, context) => {
return addFiles(options, platPrefix, projectName)(tree, context);
});
if (options.routing) {
projectChains.push((tree, context) => {
return adjustRouting(routingModulePathOptions, platPrefix)(tree, context);
});
if (options.adjustSandbox) {
projectChains.push((tree, context) => {
return adjustSandbox(platPrefix, appDirectory)(tree, context);
});
}
}
if (!options.onlyModule) {
projectChains.push((tree, context) => {
return addFiles(options, platPrefix, projectName, "_component")(tree, context);
});
}
}
}
else {
projectChains.push(schematics_1.noop());
}
return schematics_1.chain([
utils_1.prerun(),
// libs
(tree, context) => options.onlyProject
? schematics_1.noop()(tree, context)
: addFiles(options)(tree, context),
// libs
(tree, context) => options.onlyProject || !options.createBase || options.onlyModule
? schematics_1.noop()(tree, context)
: addFiles(options, null, null, "_component")(tree, context),
// update libs index
(tree, context) => options.onlyProject
? schematics_1.noop()(tree, context)
: adjustBarrelIndex("libs/features/index.ts")(tree, context),
// web
(tree, context) => !options.onlyProject && targetPlatforms.web
? addFiles(options, "web")(tree, context)
: schematics_1.noop()(tree, context),
// update web index
(tree, context) => !options.onlyProject && targetPlatforms.web
? adjustBarrelIndex("xplat/web/features/index.ts")(tree, context)
: schematics_1.noop()(tree, context),
// add starting component unless onlyModule
(tree, context) => !options.onlyProject && !options.onlyModule && targetPlatforms.web
? addFiles(options, "web", null, "_component")(tree, context)
: schematics_1.noop()(tree, context),
// nativescript
(tree, context) => !options.onlyProject && targetPlatforms.nativescript
? addFiles(options, "nativescript")(tree, context)
: schematics_1.noop()(tree, context),
// update nativescript index
(tree, context) => !options.onlyProject && targetPlatforms.nativescript
? adjustBarrelIndex("xplat/nativescript/features/index.ts")(tree, context)
: schematics_1.noop()(tree, context),
// add starting component unless onlyModule
(tree, context) => !options.onlyProject &&
!options.onlyModule &&
targetPlatforms.nativescript
? addFiles(options, "nativescript", null, "_component")(tree, context)
: schematics_1.noop()(tree, context),
// ionic
(tree, context) => !options.onlyProject && targetPlatforms.ionic
? addFiles(options, "ionic")(tree, context)
: schematics_1.noop()(tree, context),
// update ionic index
(tree, context) => !options.onlyProject && targetPlatforms.ionic
? adjustBarrelIndex("xplat/ionic/features/index.ts")(tree, context)
: schematics_1.noop()(tree, context),
// add starting component unless onlyModule
(tree, context) => !options.onlyProject && !options.onlyModule && targetPlatforms.ionic
? addFiles(options, "ionic", null, "_component")(tree, context)
: schematics_1.noop()(tree, context),
// project handling
...projectChains,
options.skipFormat ? schematics_1.noop() : utils_1.formatFiles(options)
]);
}
exports.default = default_1;
const addFiles = (options, target = "", projectName = "", extra = "") => {
let moveTo;
if (target) {
moveTo = getMoveTo(target, projectName);
}
else {
target = "lib";
moveTo = `libs/features/${featureName}`;
}
return schematics_1.branchAndMerge(schematics_1.mergeWith(schematics_1.apply(schematics_1.url(`./_${target}${extra}_files`), [
schematics_1.template(getTemplateOptions(options)),
schematics_1.move(moveTo)
])));
};
function adjustBarrelIndex(indexFilePath) {
return (host) => {
const indexSource = host.read(indexFilePath).toString("utf-8");
const indexSourceFile = ts.createSourceFile(indexFilePath, indexSource, ts.ScriptTarget.Latest, true);
utils_1.insert(host, indexFilePath, [
...utils_1.addGlobal(indexSourceFile, indexFilePath, `export * from './${featureName}';`, true)
]);
return host;
};
}
function getTemplateOptions(options) {
const nameParts = options.name.split('-');
let endingDashName = nameParts[0];
if (nameParts.length > 1) {
endingDashName = strings_1.capitalize(nameParts[nameParts.length - 1]);
}
return Object.assign({}, options, { name: featureName, endingDashName, npmScope: utils_1.getNpmScope(), prefix: utils_1.getPrefix(), dot: ".", utils: utils_1.stringUtils });
}
function getMoveTo(platform, projectName) {
let moveTo = `xplat/${platform}/features/${featureName}`;
if (projectName) {
let srcDir = platform !== "nativescript" ? "src/" : "";
moveTo = `apps/${projectName}/${srcDir}app/features/${featureName}`;
// console.log('moveTo:', moveTo);
}
return moveTo;
}
function adjustRouting(routingModulePaths, platform) {
return (host) => {
let routingModulePath;
// check which routing naming convention might be in use
// app.routing.ts or app-routing.module.ts
for (const modulePath of routingModulePaths) {
if (host.exists(modulePath)) {
routingModulePath = modulePath;
break;
}
}
// console.log('routingModulePath:',routingModulePath);
// console.log('host.exists(routingModulePath):',host.exists(routingModulePath));
if (routingModulePath) {
const routingSource = host.read(routingModulePath).toString("utf-8");
const routingSourceFile = ts.createSourceFile(routingModulePath, routingSource, ts.ScriptTarget.Latest, true);
const changes = [];
const loadPrefix = platform === "nativescript" ? "~" : ".";
// add component to route config
changes.push(...utils_1.addToCollection(routingSourceFile, routingModulePath, `{
path: '${featureName}',
loadChildren: '${loadPrefix}/features/${featureName}/${featureName}.module#${utils_1.stringUtils.classify(featureName)}Module'
}`));
utils_1.insert(host, routingModulePath, changes);
}
return host;
};
}
function adjustSandbox(platform, appDirectory) {
return (tree) => {
if (utils_1.supportedSandboxPlatforms.includes(platform)) {
const homeCmpPath = `${appDirectory}/features/home/components/home.component.html`;
let homeTemplate = test_1.getFileContent(tree, homeCmpPath);
switch (platform) {
case "nativescript":
let buttonTag = 'Button';
let buttonEndIndex = homeTemplate.lastIndexOf(`</${buttonTag}>`);
if (buttonEndIndex === -1) {
// check for lowercase
buttonEndIndex = homeTemplate.lastIndexOf(`</${buttonTag.toLowerCase()}>`);
if (buttonEndIndex > -1) {
buttonTag = buttonTag.toLowerCase();
}
}
let customBtnClass = '';
if (buttonEndIndex === -1) {
// if no buttons were found this is a fresh sandbox app setup
// it should have a label as placeholder
buttonEndIndex = homeTemplate.lastIndexOf('</Label>');
if (buttonEndIndex === -1) {
buttonEndIndex = homeTemplate.lastIndexOf(`</label>`);
}
}
else {
const buttonClassStartIndex = homeTemplate.lastIndexOf('class="btn ');
if (buttonClassStartIndex > -1) {
// using custom button class
customBtnClass = ' ' + homeTemplate.substring(buttonClassStartIndex + 11, homeTemplate.lastIndexOf(`"></${buttonTag}>`));
}
}
const featureNameParts = featureName.split("-");
let routeName = featureName;
if (featureNameParts.length > 1) {
routeName = strings_1.capitalize(featureNameParts[featureNameParts.length - 1]);
}
homeTemplate =
homeTemplate.slice(0, buttonEndIndex + 9) +
`<${buttonTag} text="${routeName}" (tap)="goTo('/${featureName}')" class="btn${customBtnClass}"></${buttonTag}>` +
homeTemplate.slice(buttonEndIndex + 9);
break;
}
utils_1.createOrUpdate(tree, homeCmpPath, homeTemplate);
}
else {
throw new schematics_1.SchematicsException(`The --adjustSandbox option is only supported on the following at the moment: ${utils_1.supportedSandboxPlatforms}`);
}
return tree;
};
}
//# sourceMappingURL=index.js.map